15118ebe8SLucas Mateus Castro (alqotel) /* 25118ebe8SLucas Mateus Castro (alqotel) * PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU. 35118ebe8SLucas Mateus Castro (alqotel) * 45118ebe8SLucas Mateus Castro (alqotel) * Copyright (c) 2003-2007 Jocelyn Mayer 55118ebe8SLucas Mateus Castro (alqotel) * 65118ebe8SLucas Mateus Castro (alqotel) * This library is free software; you can redistribute it and/or 75118ebe8SLucas Mateus Castro (alqotel) * modify it under the terms of the GNU Lesser General Public 85118ebe8SLucas Mateus Castro (alqotel) * License as published by the Free Software Foundation; either 95118ebe8SLucas Mateus Castro (alqotel) * version 2.1 of the License, or (at your option) any later version. 105118ebe8SLucas Mateus Castro (alqotel) * 115118ebe8SLucas Mateus Castro (alqotel) * This library is distributed in the hope that it will be useful, 125118ebe8SLucas Mateus Castro (alqotel) * but WITHOUT ANY WARRANTY; without even the implied warranty of 135118ebe8SLucas Mateus Castro (alqotel) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 145118ebe8SLucas Mateus Castro (alqotel) * Lesser General Public License for more details. 155118ebe8SLucas Mateus Castro (alqotel) * 165118ebe8SLucas Mateus Castro (alqotel) * You should have received a copy of the GNU Lesser General Public 175118ebe8SLucas Mateus Castro (alqotel) * License along with this library; if not, see <http://www.gnu.org/licenses/>. 185118ebe8SLucas Mateus Castro (alqotel) */ 195118ebe8SLucas Mateus Castro (alqotel) 205118ebe8SLucas Mateus Castro (alqotel) #include "qemu/osdep.h" 215118ebe8SLucas Mateus Castro (alqotel) #include "qemu/units.h" 225118ebe8SLucas Mateus Castro (alqotel) #include "cpu.h" 235118ebe8SLucas Mateus Castro (alqotel) #include "sysemu/kvm.h" 245118ebe8SLucas Mateus Castro (alqotel) #include "kvm_ppc.h" 255118ebe8SLucas Mateus Castro (alqotel) #include "mmu-hash64.h" 265118ebe8SLucas Mateus Castro (alqotel) #include "mmu-hash32.h" 275118ebe8SLucas Mateus Castro (alqotel) #include "exec/exec-all.h" 2874781c08SPhilippe Mathieu-Daudé #include "exec/page-protection.h" 295118ebe8SLucas Mateus Castro (alqotel) #include "exec/log.h" 305118ebe8SLucas Mateus Castro (alqotel) #include "helper_regs.h" 315118ebe8SLucas Mateus Castro (alqotel) #include "qemu/error-report.h" 325118ebe8SLucas Mateus Castro (alqotel) #include "qemu/qemu-print.h" 335118ebe8SLucas Mateus Castro (alqotel) #include "internal.h" 345118ebe8SLucas Mateus Castro (alqotel) #include "mmu-book3s-v3.h" 355118ebe8SLucas Mateus Castro (alqotel) #include "mmu-radix64.h" 36e7baac64SBALATON Zoltan #include "mmu-booke.h" 375118ebe8SLucas Mateus Castro (alqotel) 385118ebe8SLucas Mateus Castro (alqotel) /* #define DUMP_PAGE_TABLES */ 395118ebe8SLucas Mateus Castro (alqotel) 40306b5320SBALATON Zoltan /* Context used internally during MMU translations */ 41306b5320SBALATON Zoltan typedef struct { 42306b5320SBALATON Zoltan hwaddr raddr; /* Real address */ 43306b5320SBALATON Zoltan int prot; /* Protection bits */ 44306b5320SBALATON Zoltan target_ulong ptem; /* Virtual segment ID | API */ 45306b5320SBALATON Zoltan int key; /* Access key */ 46306b5320SBALATON Zoltan int nx; /* Non-execute area */ 47306b5320SBALATON Zoltan } mmu_ctx_t; 48306b5320SBALATON Zoltan 49d6ae8ec6SLucas Mateus Castro (alqotel) void ppc_store_sdr1(CPUPPCState *env, target_ulong value) 50d6ae8ec6SLucas Mateus Castro (alqotel) { 51d6ae8ec6SLucas Mateus Castro (alqotel) PowerPCCPU *cpu = env_archcpu(env); 52d6ae8ec6SLucas Mateus Castro (alqotel) qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value); 53d6ae8ec6SLucas Mateus Castro (alqotel) assert(!cpu->env.has_hv_mode || !cpu->vhyp); 54d6ae8ec6SLucas Mateus Castro (alqotel) #if defined(TARGET_PPC64) 55d6ae8ec6SLucas Mateus Castro (alqotel) if (mmu_is_64bit(env->mmu_model)) { 56d6ae8ec6SLucas Mateus Castro (alqotel) target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE; 57d6ae8ec6SLucas Mateus Castro (alqotel) target_ulong htabsize = value & SDR_64_HTABSIZE; 58d6ae8ec6SLucas Mateus Castro (alqotel) 59d6ae8ec6SLucas Mateus Castro (alqotel) if (value & ~sdr_mask) { 60d6ae8ec6SLucas Mateus Castro (alqotel) qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx 61d6ae8ec6SLucas Mateus Castro (alqotel) " set in SDR1", value & ~sdr_mask); 62d6ae8ec6SLucas Mateus Castro (alqotel) value &= sdr_mask; 63d6ae8ec6SLucas Mateus Castro (alqotel) } 64d6ae8ec6SLucas Mateus Castro (alqotel) if (htabsize > 28) { 65d6ae8ec6SLucas Mateus Castro (alqotel) qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx 66d6ae8ec6SLucas Mateus Castro (alqotel) " stored in SDR1", htabsize); 67d6ae8ec6SLucas Mateus Castro (alqotel) return; 68d6ae8ec6SLucas Mateus Castro (alqotel) } 69d6ae8ec6SLucas Mateus Castro (alqotel) } 70d6ae8ec6SLucas Mateus Castro (alqotel) #endif /* defined(TARGET_PPC64) */ 71d6ae8ec6SLucas Mateus Castro (alqotel) /* FIXME: Should check for valid HTABMASK values in 32-bit case */ 72d6ae8ec6SLucas Mateus Castro (alqotel) env->spr[SPR_SDR1] = value; 73d6ae8ec6SLucas Mateus Castro (alqotel) } 74d6ae8ec6SLucas Mateus Castro (alqotel) 755118ebe8SLucas Mateus Castro (alqotel) /*****************************************************************************/ 765118ebe8SLucas Mateus Castro (alqotel) /* PowerPC MMU emulation */ 775118ebe8SLucas Mateus Castro (alqotel) 785118ebe8SLucas Mateus Castro (alqotel) int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr, 795118ebe8SLucas Mateus Castro (alqotel) int way, int is_code) 805118ebe8SLucas Mateus Castro (alqotel) { 815118ebe8SLucas Mateus Castro (alqotel) int nr; 825118ebe8SLucas Mateus Castro (alqotel) 835118ebe8SLucas Mateus Castro (alqotel) /* Select TLB num in a way from address */ 845118ebe8SLucas Mateus Castro (alqotel) nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1); 855118ebe8SLucas Mateus Castro (alqotel) /* Select TLB way */ 865118ebe8SLucas Mateus Castro (alqotel) nr += env->tlb_per_way * way; 875fd257f5SBALATON Zoltan /* 6xx has separate TLBs for instructions and data */ 885fd257f5SBALATON Zoltan if (is_code) { 895118ebe8SLucas Mateus Castro (alqotel) nr += env->nb_tlb; 905118ebe8SLucas Mateus Castro (alqotel) } 915118ebe8SLucas Mateus Castro (alqotel) 925118ebe8SLucas Mateus Castro (alqotel) return nr; 935118ebe8SLucas Mateus Castro (alqotel) } 945118ebe8SLucas Mateus Castro (alqotel) 955118ebe8SLucas Mateus Castro (alqotel) static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0, 963208c36aSBALATON Zoltan target_ulong pte1, int pteh, 975118ebe8SLucas Mateus Castro (alqotel) MMUAccessType access_type) 985118ebe8SLucas Mateus Castro (alqotel) { 995118ebe8SLucas Mateus Castro (alqotel) /* Check validity and table match */ 1009e2d6802SBALATON Zoltan if (!pte_is_valid(pte0) || ((pte0 >> 6) & 1) != pteh || 1019e2d6802SBALATON Zoltan (pte0 & PTE_PTEM_MASK) != ctx->ptem) { 1029e2d6802SBALATON Zoltan return -1; 1039e2d6802SBALATON Zoltan } 1045118ebe8SLucas Mateus Castro (alqotel) /* all matches should have equal RPN, WIMG & PP */ 1059e2d6802SBALATON Zoltan if (ctx->raddr != (hwaddr)-1ULL && 1069e2d6802SBALATON Zoltan (ctx->raddr & PTE_CHECK_MASK) != (pte1 & PTE_CHECK_MASK)) { 1075118ebe8SLucas Mateus Castro (alqotel) qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n"); 1085118ebe8SLucas Mateus Castro (alqotel) return -3; 1095118ebe8SLucas Mateus Castro (alqotel) } 1105118ebe8SLucas Mateus Castro (alqotel) /* Keep the matching PTE information */ 1115118ebe8SLucas Mateus Castro (alqotel) ctx->raddr = pte1; 1127ee01cf8SBALATON Zoltan ctx->prot = ppc_hash32_prot(ctx->key, pte1 & HPTE32_R_PP, ctx->nx); 113cd1038ecSBALATON Zoltan if (check_prot_access_type(ctx->prot, access_type)) { 1145118ebe8SLucas Mateus Castro (alqotel) qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n"); 1150e65cea1SBALATON Zoltan return 0; 1165118ebe8SLucas Mateus Castro (alqotel) } else { 1175118ebe8SLucas Mateus Castro (alqotel) qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n"); 1180e65cea1SBALATON Zoltan return -2; 1195118ebe8SLucas Mateus Castro (alqotel) } 1205118ebe8SLucas Mateus Castro (alqotel) } 1215118ebe8SLucas Mateus Castro (alqotel) 1225118ebe8SLucas Mateus Castro (alqotel) static int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p, 1235118ebe8SLucas Mateus Castro (alqotel) int ret, MMUAccessType access_type) 1245118ebe8SLucas Mateus Castro (alqotel) { 1255118ebe8SLucas Mateus Castro (alqotel) int store = 0; 1265118ebe8SLucas Mateus Castro (alqotel) 1275118ebe8SLucas Mateus Castro (alqotel) /* Update page flags */ 1285118ebe8SLucas Mateus Castro (alqotel) if (!(*pte1p & 0x00000100)) { 1295118ebe8SLucas Mateus Castro (alqotel) /* Update accessed flag */ 1305118ebe8SLucas Mateus Castro (alqotel) *pte1p |= 0x00000100; 1315118ebe8SLucas Mateus Castro (alqotel) store = 1; 1325118ebe8SLucas Mateus Castro (alqotel) } 1335118ebe8SLucas Mateus Castro (alqotel) if (!(*pte1p & 0x00000080)) { 1345118ebe8SLucas Mateus Castro (alqotel) if (access_type == MMU_DATA_STORE && ret == 0) { 1355118ebe8SLucas Mateus Castro (alqotel) /* Update changed flag */ 1365118ebe8SLucas Mateus Castro (alqotel) *pte1p |= 0x00000080; 1375118ebe8SLucas Mateus Castro (alqotel) store = 1; 1385118ebe8SLucas Mateus Castro (alqotel) } else { 1395118ebe8SLucas Mateus Castro (alqotel) /* Force page fault for first write access */ 1405118ebe8SLucas Mateus Castro (alqotel) ctx->prot &= ~PAGE_WRITE; 1415118ebe8SLucas Mateus Castro (alqotel) } 1425118ebe8SLucas Mateus Castro (alqotel) } 1435118ebe8SLucas Mateus Castro (alqotel) 1445118ebe8SLucas Mateus Castro (alqotel) return store; 1455118ebe8SLucas Mateus Castro (alqotel) } 1465118ebe8SLucas Mateus Castro (alqotel) 1475118ebe8SLucas Mateus Castro (alqotel) /* Software driven TLB helpers */ 1485118ebe8SLucas Mateus Castro (alqotel) 1495118ebe8SLucas Mateus Castro (alqotel) static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx, 1505118ebe8SLucas Mateus Castro (alqotel) target_ulong eaddr, MMUAccessType access_type) 1515118ebe8SLucas Mateus Castro (alqotel) { 1525118ebe8SLucas Mateus Castro (alqotel) ppc6xx_tlb_t *tlb; 1535118ebe8SLucas Mateus Castro (alqotel) int nr, best, way; 1545118ebe8SLucas Mateus Castro (alqotel) int ret; 1555118ebe8SLucas Mateus Castro (alqotel) 1565118ebe8SLucas Mateus Castro (alqotel) best = -1; 1575118ebe8SLucas Mateus Castro (alqotel) ret = -1; /* No TLB found */ 1585118ebe8SLucas Mateus Castro (alqotel) for (way = 0; way < env->nb_ways; way++) { 1595118ebe8SLucas Mateus Castro (alqotel) nr = ppc6xx_tlb_getnum(env, eaddr, way, access_type == MMU_INST_FETCH); 1605118ebe8SLucas Mateus Castro (alqotel) tlb = &env->tlb.tlb6[nr]; 1615118ebe8SLucas Mateus Castro (alqotel) /* This test "emulates" the PTE index match for hardware TLBs */ 1625118ebe8SLucas Mateus Castro (alqotel) if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) { 16356964585SCédric Le Goater qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx 16456964585SCédric Le Goater " " TARGET_FMT_lx "] <> " TARGET_FMT_lx "\n", 16556964585SCédric Le Goater nr, env->nb_tlb, 1665118ebe8SLucas Mateus Castro (alqotel) pte_is_valid(tlb->pte0) ? "valid" : "inval", 1675118ebe8SLucas Mateus Castro (alqotel) tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr); 1685118ebe8SLucas Mateus Castro (alqotel) continue; 1695118ebe8SLucas Mateus Castro (alqotel) } 17056964585SCédric Le Goater qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s " TARGET_FMT_lx " <> " 17156964585SCédric Le Goater TARGET_FMT_lx " " TARGET_FMT_lx " %c %c\n", 17256964585SCédric Le Goater nr, env->nb_tlb, 1735118ebe8SLucas Mateus Castro (alqotel) pte_is_valid(tlb->pte0) ? "valid" : "inval", 1745118ebe8SLucas Mateus Castro (alqotel) tlb->EPN, eaddr, tlb->pte1, 1755118ebe8SLucas Mateus Castro (alqotel) access_type == MMU_DATA_STORE ? 'S' : 'L', 1765118ebe8SLucas Mateus Castro (alqotel) access_type == MMU_INST_FETCH ? 'I' : 'D'); 1775118ebe8SLucas Mateus Castro (alqotel) switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1, 1785118ebe8SLucas Mateus Castro (alqotel) 0, access_type)) { 1795118ebe8SLucas Mateus Castro (alqotel) case -2: 1805118ebe8SLucas Mateus Castro (alqotel) /* Access violation */ 1815118ebe8SLucas Mateus Castro (alqotel) ret = -2; 1825118ebe8SLucas Mateus Castro (alqotel) best = nr; 1835118ebe8SLucas Mateus Castro (alqotel) break; 1840af20f35SBALATON Zoltan case -1: /* No match */ 1850af20f35SBALATON Zoltan case -3: /* TLB inconsistency */ 1865118ebe8SLucas Mateus Castro (alqotel) default: 1875118ebe8SLucas Mateus Castro (alqotel) break; 1885118ebe8SLucas Mateus Castro (alqotel) case 0: 1895118ebe8SLucas Mateus Castro (alqotel) /* access granted */ 1905118ebe8SLucas Mateus Castro (alqotel) /* 1915118ebe8SLucas Mateus Castro (alqotel) * XXX: we should go on looping to check all TLBs 1925118ebe8SLucas Mateus Castro (alqotel) * consistency but we can speed-up the whole thing as 1935118ebe8SLucas Mateus Castro (alqotel) * the result would be undefined if TLBs are not 1945118ebe8SLucas Mateus Castro (alqotel) * consistent. 1955118ebe8SLucas Mateus Castro (alqotel) */ 1965118ebe8SLucas Mateus Castro (alqotel) ret = 0; 1975118ebe8SLucas Mateus Castro (alqotel) best = nr; 1985118ebe8SLucas Mateus Castro (alqotel) goto done; 1995118ebe8SLucas Mateus Castro (alqotel) } 2005118ebe8SLucas Mateus Castro (alqotel) } 2015118ebe8SLucas Mateus Castro (alqotel) if (best != -1) { 2025118ebe8SLucas Mateus Castro (alqotel) done: 203883f2c59SPhilippe Mathieu-Daudé qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx 20456964585SCédric Le Goater " prot=%01x ret=%d\n", 2055118ebe8SLucas Mateus Castro (alqotel) ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret); 2065118ebe8SLucas Mateus Castro (alqotel) /* Update page flags */ 2075118ebe8SLucas Mateus Castro (alqotel) pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, access_type); 2085118ebe8SLucas Mateus Castro (alqotel) } 2090af20f35SBALATON Zoltan #if defined(DUMP_PAGE_TABLES) 2100af20f35SBALATON Zoltan if (qemu_loglevel_mask(CPU_LOG_MMU)) { 2110af20f35SBALATON Zoltan CPUState *cs = env_cpu(env); 2120af20f35SBALATON Zoltan hwaddr base = ppc_hash32_hpt_base(env_archcpu(env)); 2130af20f35SBALATON Zoltan hwaddr len = ppc_hash32_hpt_mask(env_archcpu(env)) + 0x80; 2140af20f35SBALATON Zoltan uint32_t a0, a1, a2, a3; 2155118ebe8SLucas Mateus Castro (alqotel) 2160af20f35SBALATON Zoltan qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n", 2170af20f35SBALATON Zoltan base, len); 2180af20f35SBALATON Zoltan for (hwaddr curaddr = base; curaddr < base + len; curaddr += 16) { 2190af20f35SBALATON Zoltan a0 = ldl_phys(cs->as, curaddr); 2200af20f35SBALATON Zoltan a1 = ldl_phys(cs->as, curaddr + 4); 2210af20f35SBALATON Zoltan a2 = ldl_phys(cs->as, curaddr + 8); 2220af20f35SBALATON Zoltan a3 = ldl_phys(cs->as, curaddr + 12); 2230af20f35SBALATON Zoltan if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) { 2240af20f35SBALATON Zoltan qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n", 2250af20f35SBALATON Zoltan curaddr, a0, a1, a2, a3); 2260af20f35SBALATON Zoltan } 2270af20f35SBALATON Zoltan } 2280af20f35SBALATON Zoltan } 2290af20f35SBALATON Zoltan #endif 2305118ebe8SLucas Mateus Castro (alqotel) return ret; 2315118ebe8SLucas Mateus Castro (alqotel) } 2325118ebe8SLucas Mateus Castro (alqotel) 2335118ebe8SLucas Mateus Castro (alqotel) /* Perform BAT hit & translation */ 2345118ebe8SLucas Mateus Castro (alqotel) static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp, 2355118ebe8SLucas Mateus Castro (alqotel) int *validp, int *protp, target_ulong *BATu, 2365118ebe8SLucas Mateus Castro (alqotel) target_ulong *BATl) 2375118ebe8SLucas Mateus Castro (alqotel) { 2385118ebe8SLucas Mateus Castro (alqotel) target_ulong bl; 2395118ebe8SLucas Mateus Castro (alqotel) int pp, valid, prot; 2405118ebe8SLucas Mateus Castro (alqotel) 2415118ebe8SLucas Mateus Castro (alqotel) bl = (*BATu & 0x00001FFC) << 15; 2425118ebe8SLucas Mateus Castro (alqotel) valid = 0; 2435118ebe8SLucas Mateus Castro (alqotel) prot = 0; 244d41ccf6eSVíctor Colombo if ((!FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000002)) || 245d41ccf6eSVíctor Colombo (FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000001))) { 2465118ebe8SLucas Mateus Castro (alqotel) valid = 1; 2475118ebe8SLucas Mateus Castro (alqotel) pp = *BATl & 0x00000003; 2485118ebe8SLucas Mateus Castro (alqotel) if (pp != 0) { 2495118ebe8SLucas Mateus Castro (alqotel) prot = PAGE_READ | PAGE_EXEC; 2505118ebe8SLucas Mateus Castro (alqotel) if (pp == 0x2) { 2515118ebe8SLucas Mateus Castro (alqotel) prot |= PAGE_WRITE; 2525118ebe8SLucas Mateus Castro (alqotel) } 2535118ebe8SLucas Mateus Castro (alqotel) } 2545118ebe8SLucas Mateus Castro (alqotel) } 2555118ebe8SLucas Mateus Castro (alqotel) *blp = bl; 2565118ebe8SLucas Mateus Castro (alqotel) *validp = valid; 2575118ebe8SLucas Mateus Castro (alqotel) *protp = prot; 2585118ebe8SLucas Mateus Castro (alqotel) } 2595118ebe8SLucas Mateus Castro (alqotel) 2605118ebe8SLucas Mateus Castro (alqotel) static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, 2615118ebe8SLucas Mateus Castro (alqotel) target_ulong virtual, MMUAccessType access_type) 2625118ebe8SLucas Mateus Castro (alqotel) { 2635118ebe8SLucas Mateus Castro (alqotel) target_ulong *BATlt, *BATut, *BATu, *BATl; 2645118ebe8SLucas Mateus Castro (alqotel) target_ulong BEPIl, BEPIu, bl; 2655118ebe8SLucas Mateus Castro (alqotel) int i, valid, prot; 2665118ebe8SLucas Mateus Castro (alqotel) int ret = -1; 2675118ebe8SLucas Mateus Castro (alqotel) bool ifetch = access_type == MMU_INST_FETCH; 2685118ebe8SLucas Mateus Castro (alqotel) 26956964585SCédric Le Goater qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__, 2705118ebe8SLucas Mateus Castro (alqotel) ifetch ? 'I' : 'D', virtual); 2715118ebe8SLucas Mateus Castro (alqotel) if (ifetch) { 2725118ebe8SLucas Mateus Castro (alqotel) BATlt = env->IBAT[1]; 2735118ebe8SLucas Mateus Castro (alqotel) BATut = env->IBAT[0]; 2745118ebe8SLucas Mateus Castro (alqotel) } else { 2755118ebe8SLucas Mateus Castro (alqotel) BATlt = env->DBAT[1]; 2765118ebe8SLucas Mateus Castro (alqotel) BATut = env->DBAT[0]; 2775118ebe8SLucas Mateus Castro (alqotel) } 2785118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < env->nb_BATs; i++) { 2795118ebe8SLucas Mateus Castro (alqotel) BATu = &BATut[i]; 2805118ebe8SLucas Mateus Castro (alqotel) BATl = &BATlt[i]; 2815118ebe8SLucas Mateus Castro (alqotel) BEPIu = *BATu & 0xF0000000; 2825118ebe8SLucas Mateus Castro (alqotel) BEPIl = *BATu & 0x0FFE0000; 2835118ebe8SLucas Mateus Castro (alqotel) bat_size_prot(env, &bl, &valid, &prot, BATu, BATl); 28456964585SCédric Le Goater qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu " 28556964585SCédric Le Goater TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__, 2865118ebe8SLucas Mateus Castro (alqotel) ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl); 2875118ebe8SLucas Mateus Castro (alqotel) if ((virtual & 0xF0000000) == BEPIu && 2885118ebe8SLucas Mateus Castro (alqotel) ((virtual & 0x0FFE0000) & ~bl) == BEPIl) { 2895118ebe8SLucas Mateus Castro (alqotel) /* BAT matches */ 2905118ebe8SLucas Mateus Castro (alqotel) if (valid != 0) { 2915118ebe8SLucas Mateus Castro (alqotel) /* Get physical address */ 2925118ebe8SLucas Mateus Castro (alqotel) ctx->raddr = (*BATl & 0xF0000000) | 2935118ebe8SLucas Mateus Castro (alqotel) ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) | 2945118ebe8SLucas Mateus Castro (alqotel) (virtual & 0x0001F000); 2955118ebe8SLucas Mateus Castro (alqotel) /* Compute access rights */ 2965118ebe8SLucas Mateus Castro (alqotel) ctx->prot = prot; 297cd1038ecSBALATON Zoltan if (check_prot_access_type(ctx->prot, access_type)) { 298883f2c59SPhilippe Mathieu-Daudé qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " HWADDR_FMT_plx 29956964585SCédric Le Goater " prot=%c%c\n", i, ctx->raddr, 30056964585SCédric Le Goater ctx->prot & PAGE_READ ? 'R' : '-', 3015118ebe8SLucas Mateus Castro (alqotel) ctx->prot & PAGE_WRITE ? 'W' : '-'); 302cd1038ecSBALATON Zoltan ret = 0; 303cd1038ecSBALATON Zoltan } else { 304cd1038ecSBALATON Zoltan ret = -2; 3055118ebe8SLucas Mateus Castro (alqotel) } 3065118ebe8SLucas Mateus Castro (alqotel) break; 3075118ebe8SLucas Mateus Castro (alqotel) } 3085118ebe8SLucas Mateus Castro (alqotel) } 3095118ebe8SLucas Mateus Castro (alqotel) } 3105118ebe8SLucas Mateus Castro (alqotel) if (ret < 0) { 3115118ebe8SLucas Mateus Castro (alqotel) if (qemu_log_enabled()) { 31256964585SCédric Le Goater qemu_log_mask(CPU_LOG_MMU, "no BAT match for " 31356964585SCédric Le Goater TARGET_FMT_lx ":\n", virtual); 3145118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < 4; i++) { 3155118ebe8SLucas Mateus Castro (alqotel) BATu = &BATut[i]; 3165118ebe8SLucas Mateus Castro (alqotel) BATl = &BATlt[i]; 3175118ebe8SLucas Mateus Castro (alqotel) BEPIu = *BATu & 0xF0000000; 3185118ebe8SLucas Mateus Castro (alqotel) BEPIl = *BATu & 0x0FFE0000; 3195118ebe8SLucas Mateus Castro (alqotel) bl = (*BATu & 0x00001FFC) << 15; 32047bededcSBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx 32147bededcSBALATON Zoltan " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx 32247bededcSBALATON Zoltan "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " " 32347bededcSBALATON Zoltan TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D', 32447bededcSBALATON Zoltan i, virtual, *BATu, *BATl, BEPIu, BEPIl, bl); 3255118ebe8SLucas Mateus Castro (alqotel) } 3265118ebe8SLucas Mateus Castro (alqotel) } 3275118ebe8SLucas Mateus Castro (alqotel) } 3285118ebe8SLucas Mateus Castro (alqotel) /* No hit */ 3295118ebe8SLucas Mateus Castro (alqotel) return ret; 3305118ebe8SLucas Mateus Castro (alqotel) } 3315118ebe8SLucas Mateus Castro (alqotel) 332269d6f00SBALATON Zoltan static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, 333*f6f8838bSBALATON Zoltan target_ulong eaddr, hwaddr *hashp, 334269d6f00SBALATON Zoltan MMUAccessType access_type, int type) 3355118ebe8SLucas Mateus Castro (alqotel) { 3365118ebe8SLucas Mateus Castro (alqotel) PowerPCCPU *cpu = env_archcpu(env); 3375118ebe8SLucas Mateus Castro (alqotel) hwaddr hash; 338269d6f00SBALATON Zoltan target_ulong vsid, sr, pgidx; 339d41ccf6eSVíctor Colombo int ds, target_page_bits; 340d41ccf6eSVíctor Colombo bool pr; 3415118ebe8SLucas Mateus Castro (alqotel) 342269d6f00SBALATON Zoltan /* First try to find a BAT entry if there are any */ 343269d6f00SBALATON Zoltan if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) { 344269d6f00SBALATON Zoltan return 0; 345269d6f00SBALATON Zoltan } 346269d6f00SBALATON Zoltan 347269d6f00SBALATON Zoltan /* Perform segment based translation when no BATs matched */ 348d41ccf6eSVíctor Colombo pr = FIELD_EX64(env->msr, MSR, PR); 3495118ebe8SLucas Mateus Castro (alqotel) 3505118ebe8SLucas Mateus Castro (alqotel) sr = env->sr[eaddr >> 28]; 351d41ccf6eSVíctor Colombo ctx->key = (((sr & 0x20000000) && pr) || 352d41ccf6eSVíctor Colombo ((sr & 0x40000000) && !pr)) ? 1 : 0; 3535118ebe8SLucas Mateus Castro (alqotel) ds = sr & 0x80000000 ? 1 : 0; 3545118ebe8SLucas Mateus Castro (alqotel) ctx->nx = sr & 0x10000000 ? 1 : 0; 3555118ebe8SLucas Mateus Castro (alqotel) vsid = sr & 0x00FFFFFF; 3565118ebe8SLucas Mateus Castro (alqotel) target_page_bits = TARGET_PAGE_BITS; 3575118ebe8SLucas Mateus Castro (alqotel) qemu_log_mask(CPU_LOG_MMU, 3585118ebe8SLucas Mateus Castro (alqotel) "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx 3595118ebe8SLucas Mateus Castro (alqotel) " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx 3605118ebe8SLucas Mateus Castro (alqotel) " ir=%d dr=%d pr=%d %d t=%d\n", 361d41ccf6eSVíctor Colombo eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, 362e4eea6efSVíctor Colombo (int)FIELD_EX64(env->msr, MSR, IR), 363e4eea6efSVíctor Colombo (int)FIELD_EX64(env->msr, MSR, DR), pr ? 1 : 0, 36456964585SCédric Le Goater access_type == MMU_DATA_STORE, type); 3655118ebe8SLucas Mateus Castro (alqotel) pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits; 3665118ebe8SLucas Mateus Castro (alqotel) hash = vsid ^ pgidx; 3675118ebe8SLucas Mateus Castro (alqotel) ctx->ptem = (vsid << 7) | (pgidx >> 10); 3685118ebe8SLucas Mateus Castro (alqotel) 36947bededcSBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid " 37047bededcSBALATON Zoltan TARGET_FMT_lx "\n", ctx->key, ds, ctx->nx, vsid); 3715118ebe8SLucas Mateus Castro (alqotel) if (!ds) { 3725118ebe8SLucas Mateus Castro (alqotel) /* Check if instruction fetch is allowed, if needed */ 373f1418bdeSBALATON Zoltan if (type == ACCESS_CODE && ctx->nx) { 374f1418bdeSBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "No access allowed\n"); 375f1418bdeSBALATON Zoltan return -3; 376f1418bdeSBALATON Zoltan } 3775118ebe8SLucas Mateus Castro (alqotel) /* Page address translation */ 378f1418bdeSBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask " 379f1418bdeSBALATON Zoltan HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n", 3805118ebe8SLucas Mateus Castro (alqotel) ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash); 381*f6f8838bSBALATON Zoltan *hashp = hash; 3825118ebe8SLucas Mateus Castro (alqotel) 3835118ebe8SLucas Mateus Castro (alqotel) /* Initialize real address with an invalid value */ 3845118ebe8SLucas Mateus Castro (alqotel) ctx->raddr = (hwaddr)-1ULL; 3855118ebe8SLucas Mateus Castro (alqotel) /* Software TLB search */ 386f3f66a31SBALATON Zoltan return ppc6xx_tlb_check(env, ctx, eaddr, access_type); 387f3f66a31SBALATON Zoltan } 3885118ebe8SLucas Mateus Castro (alqotel) 389f3f66a31SBALATON Zoltan /* Direct-store segment : absolutely *BUGGY* for now */ 390f3f66a31SBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "direct store...\n"); 3915118ebe8SLucas Mateus Castro (alqotel) switch (type) { 3925118ebe8SLucas Mateus Castro (alqotel) case ACCESS_INT: 3935118ebe8SLucas Mateus Castro (alqotel) /* Integer load/store : only access allowed */ 3945118ebe8SLucas Mateus Castro (alqotel) break; 3955118ebe8SLucas Mateus Castro (alqotel) case ACCESS_CODE: 3965118ebe8SLucas Mateus Castro (alqotel) /* No code fetch is allowed in direct-store areas */ 3975118ebe8SLucas Mateus Castro (alqotel) return -4; 3985118ebe8SLucas Mateus Castro (alqotel) case ACCESS_FLOAT: 3995118ebe8SLucas Mateus Castro (alqotel) /* Floating point load/store */ 4005118ebe8SLucas Mateus Castro (alqotel) return -4; 4015118ebe8SLucas Mateus Castro (alqotel) case ACCESS_RES: 4025118ebe8SLucas Mateus Castro (alqotel) /* lwarx, ldarx or srwcx. */ 4035118ebe8SLucas Mateus Castro (alqotel) return -4; 4045118ebe8SLucas Mateus Castro (alqotel) case ACCESS_CACHE: 4055118ebe8SLucas Mateus Castro (alqotel) /* 4065118ebe8SLucas Mateus Castro (alqotel) * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi 4075118ebe8SLucas Mateus Castro (alqotel) * 4085118ebe8SLucas Mateus Castro (alqotel) * Should make the instruction do no-op. As it already do 4095118ebe8SLucas Mateus Castro (alqotel) * no-op, it's quite easy :-) 4105118ebe8SLucas Mateus Castro (alqotel) */ 4115118ebe8SLucas Mateus Castro (alqotel) ctx->raddr = eaddr; 4125118ebe8SLucas Mateus Castro (alqotel) return 0; 4135118ebe8SLucas Mateus Castro (alqotel) case ACCESS_EXT: 4145118ebe8SLucas Mateus Castro (alqotel) /* eciwx or ecowx */ 4155118ebe8SLucas Mateus Castro (alqotel) return -4; 4165118ebe8SLucas Mateus Castro (alqotel) default: 417f3f66a31SBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need address" 418f3f66a31SBALATON Zoltan " translation\n"); 4195118ebe8SLucas Mateus Castro (alqotel) return -4; 4205118ebe8SLucas Mateus Castro (alqotel) } 4215118ebe8SLucas Mateus Castro (alqotel) if ((access_type == MMU_DATA_STORE || ctx->key != 1) && 4225118ebe8SLucas Mateus Castro (alqotel) (access_type == MMU_DATA_LOAD || ctx->key != 0)) { 4235118ebe8SLucas Mateus Castro (alqotel) ctx->raddr = eaddr; 424f3f66a31SBALATON Zoltan return 2; 4255118ebe8SLucas Mateus Castro (alqotel) } 426f3f66a31SBALATON Zoltan return -2; 4275118ebe8SLucas Mateus Castro (alqotel) } 4285118ebe8SLucas Mateus Castro (alqotel) 4295118ebe8SLucas Mateus Castro (alqotel) static const char *book3e_tsize_to_str[32] = { 4305118ebe8SLucas Mateus Castro (alqotel) "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", 4315118ebe8SLucas Mateus Castro (alqotel) "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M", 4325118ebe8SLucas Mateus Castro (alqotel) "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G", 4335118ebe8SLucas Mateus Castro (alqotel) "1T", "2T" 4345118ebe8SLucas Mateus Castro (alqotel) }; 4355118ebe8SLucas Mateus Castro (alqotel) 4365118ebe8SLucas Mateus Castro (alqotel) static void mmubooke_dump_mmu(CPUPPCState *env) 4375118ebe8SLucas Mateus Castro (alqotel) { 4385118ebe8SLucas Mateus Castro (alqotel) ppcemb_tlb_t *entry; 4395118ebe8SLucas Mateus Castro (alqotel) int i; 4405118ebe8SLucas Mateus Castro (alqotel) 44105739977SPhilippe Mathieu-Daudé #ifdef CONFIG_KVM 4425118ebe8SLucas Mateus Castro (alqotel) if (kvm_enabled() && !env->kvm_sw_tlb) { 4435118ebe8SLucas Mateus Castro (alqotel) qemu_printf("Cannot access KVM TLB\n"); 4445118ebe8SLucas Mateus Castro (alqotel) return; 4455118ebe8SLucas Mateus Castro (alqotel) } 44605739977SPhilippe Mathieu-Daudé #endif 4475118ebe8SLucas Mateus Castro (alqotel) 4485118ebe8SLucas Mateus Castro (alqotel) qemu_printf("\nTLB:\n"); 4495118ebe8SLucas Mateus Castro (alqotel) qemu_printf("Effective Physical Size PID Prot " 4505118ebe8SLucas Mateus Castro (alqotel) "Attr\n"); 4515118ebe8SLucas Mateus Castro (alqotel) 4525118ebe8SLucas Mateus Castro (alqotel) entry = &env->tlb.tlbe[0]; 4535118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < env->nb_tlb; i++, entry++) { 4545118ebe8SLucas Mateus Castro (alqotel) hwaddr ea, pa; 4555118ebe8SLucas Mateus Castro (alqotel) target_ulong mask; 4565118ebe8SLucas Mateus Castro (alqotel) uint64_t size = (uint64_t)entry->size; 4575118ebe8SLucas Mateus Castro (alqotel) char size_buf[20]; 4585118ebe8SLucas Mateus Castro (alqotel) 4595118ebe8SLucas Mateus Castro (alqotel) /* Check valid flag */ 4605118ebe8SLucas Mateus Castro (alqotel) if (!(entry->prot & PAGE_VALID)) { 4615118ebe8SLucas Mateus Castro (alqotel) continue; 4625118ebe8SLucas Mateus Castro (alqotel) } 4635118ebe8SLucas Mateus Castro (alqotel) 4645118ebe8SLucas Mateus Castro (alqotel) mask = ~(entry->size - 1); 4655118ebe8SLucas Mateus Castro (alqotel) ea = entry->EPN & mask; 4665118ebe8SLucas Mateus Castro (alqotel) pa = entry->RPN & mask; 4675118ebe8SLucas Mateus Castro (alqotel) /* Extend the physical address to 36 bits */ 4685118ebe8SLucas Mateus Castro (alqotel) pa |= (hwaddr)(entry->RPN & 0xF) << 32; 4695118ebe8SLucas Mateus Castro (alqotel) if (size >= 1 * MiB) { 4705118ebe8SLucas Mateus Castro (alqotel) snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB); 4715118ebe8SLucas Mateus Castro (alqotel) } else { 4725118ebe8SLucas Mateus Castro (alqotel) snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB); 4735118ebe8SLucas Mateus Castro (alqotel) } 4745118ebe8SLucas Mateus Castro (alqotel) qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n", 4755118ebe8SLucas Mateus Castro (alqotel) (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID, 4765118ebe8SLucas Mateus Castro (alqotel) entry->prot, entry->attr); 4775118ebe8SLucas Mateus Castro (alqotel) } 4785118ebe8SLucas Mateus Castro (alqotel) 4795118ebe8SLucas Mateus Castro (alqotel) } 4805118ebe8SLucas Mateus Castro (alqotel) 4815118ebe8SLucas Mateus Castro (alqotel) static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset, 4825118ebe8SLucas Mateus Castro (alqotel) int tlbsize) 4835118ebe8SLucas Mateus Castro (alqotel) { 4845118ebe8SLucas Mateus Castro (alqotel) ppcmas_tlb_t *entry; 4855118ebe8SLucas Mateus Castro (alqotel) int i; 4865118ebe8SLucas Mateus Castro (alqotel) 4875118ebe8SLucas Mateus Castro (alqotel) qemu_printf("\nTLB%d:\n", tlbn); 4885118ebe8SLucas Mateus Castro (alqotel) qemu_printf("Effective Physical Size TID TS SRWX" 4895118ebe8SLucas Mateus Castro (alqotel) " URWX WIMGE U0123\n"); 4905118ebe8SLucas Mateus Castro (alqotel) 4915118ebe8SLucas Mateus Castro (alqotel) entry = &env->tlb.tlbm[offset]; 4925118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < tlbsize; i++, entry++) { 4935118ebe8SLucas Mateus Castro (alqotel) hwaddr ea, pa, size; 4945118ebe8SLucas Mateus Castro (alqotel) int tsize; 4955118ebe8SLucas Mateus Castro (alqotel) 4965118ebe8SLucas Mateus Castro (alqotel) if (!(entry->mas1 & MAS1_VALID)) { 4975118ebe8SLucas Mateus Castro (alqotel) continue; 4985118ebe8SLucas Mateus Castro (alqotel) } 4995118ebe8SLucas Mateus Castro (alqotel) 5005118ebe8SLucas Mateus Castro (alqotel) tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT; 5015118ebe8SLucas Mateus Castro (alqotel) size = 1024ULL << tsize; 5025118ebe8SLucas Mateus Castro (alqotel) ea = entry->mas2 & ~(size - 1); 5035118ebe8SLucas Mateus Castro (alqotel) pa = entry->mas7_3 & ~(size - 1); 5045118ebe8SLucas Mateus Castro (alqotel) 5055118ebe8SLucas Mateus Castro (alqotel) qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u S%c%c%c" 5065118ebe8SLucas Mateus Castro (alqotel) " U%c%c%c %c%c%c%c%c U%c%c%c%c\n", 5075118ebe8SLucas Mateus Castro (alqotel) (uint64_t)ea, (uint64_t)pa, 5085118ebe8SLucas Mateus Castro (alqotel) book3e_tsize_to_str[tsize], 5095118ebe8SLucas Mateus Castro (alqotel) (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT, 5105118ebe8SLucas Mateus Castro (alqotel) (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT, 5115118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_SR ? 'R' : '-', 5125118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_SW ? 'W' : '-', 5135118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_SX ? 'X' : '-', 5145118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_UR ? 'R' : '-', 5155118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_UW ? 'W' : '-', 5165118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_UX ? 'X' : '-', 5175118ebe8SLucas Mateus Castro (alqotel) entry->mas2 & MAS2_W ? 'W' : '-', 5185118ebe8SLucas Mateus Castro (alqotel) entry->mas2 & MAS2_I ? 'I' : '-', 5195118ebe8SLucas Mateus Castro (alqotel) entry->mas2 & MAS2_M ? 'M' : '-', 5205118ebe8SLucas Mateus Castro (alqotel) entry->mas2 & MAS2_G ? 'G' : '-', 5215118ebe8SLucas Mateus Castro (alqotel) entry->mas2 & MAS2_E ? 'E' : '-', 5225118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_U0 ? '0' : '-', 5235118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_U1 ? '1' : '-', 5245118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_U2 ? '2' : '-', 5255118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_U3 ? '3' : '-'); 5265118ebe8SLucas Mateus Castro (alqotel) } 5275118ebe8SLucas Mateus Castro (alqotel) } 5285118ebe8SLucas Mateus Castro (alqotel) 5295118ebe8SLucas Mateus Castro (alqotel) static void mmubooke206_dump_mmu(CPUPPCState *env) 5305118ebe8SLucas Mateus Castro (alqotel) { 5315118ebe8SLucas Mateus Castro (alqotel) int offset = 0; 5325118ebe8SLucas Mateus Castro (alqotel) int i; 5335118ebe8SLucas Mateus Castro (alqotel) 53405739977SPhilippe Mathieu-Daudé #ifdef CONFIG_KVM 5355118ebe8SLucas Mateus Castro (alqotel) if (kvm_enabled() && !env->kvm_sw_tlb) { 5365118ebe8SLucas Mateus Castro (alqotel) qemu_printf("Cannot access KVM TLB\n"); 5375118ebe8SLucas Mateus Castro (alqotel) return; 5385118ebe8SLucas Mateus Castro (alqotel) } 53905739977SPhilippe Mathieu-Daudé #endif 5405118ebe8SLucas Mateus Castro (alqotel) 5415118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 5425118ebe8SLucas Mateus Castro (alqotel) int size = booke206_tlb_size(env, i); 5435118ebe8SLucas Mateus Castro (alqotel) 5445118ebe8SLucas Mateus Castro (alqotel) if (size == 0) { 5455118ebe8SLucas Mateus Castro (alqotel) continue; 5465118ebe8SLucas Mateus Castro (alqotel) } 5475118ebe8SLucas Mateus Castro (alqotel) 5485118ebe8SLucas Mateus Castro (alqotel) mmubooke206_dump_one_tlb(env, i, offset, size); 5495118ebe8SLucas Mateus Castro (alqotel) offset += size; 5505118ebe8SLucas Mateus Castro (alqotel) } 5515118ebe8SLucas Mateus Castro (alqotel) } 5525118ebe8SLucas Mateus Castro (alqotel) 5535118ebe8SLucas Mateus Castro (alqotel) static void mmu6xx_dump_BATs(CPUPPCState *env, int type) 5545118ebe8SLucas Mateus Castro (alqotel) { 5555118ebe8SLucas Mateus Castro (alqotel) target_ulong *BATlt, *BATut, *BATu, *BATl; 5565118ebe8SLucas Mateus Castro (alqotel) target_ulong BEPIl, BEPIu, bl; 5575118ebe8SLucas Mateus Castro (alqotel) int i; 5585118ebe8SLucas Mateus Castro (alqotel) 5595118ebe8SLucas Mateus Castro (alqotel) switch (type) { 5605118ebe8SLucas Mateus Castro (alqotel) case ACCESS_CODE: 5615118ebe8SLucas Mateus Castro (alqotel) BATlt = env->IBAT[1]; 5625118ebe8SLucas Mateus Castro (alqotel) BATut = env->IBAT[0]; 5635118ebe8SLucas Mateus Castro (alqotel) break; 5645118ebe8SLucas Mateus Castro (alqotel) default: 5655118ebe8SLucas Mateus Castro (alqotel) BATlt = env->DBAT[1]; 5665118ebe8SLucas Mateus Castro (alqotel) BATut = env->DBAT[0]; 5675118ebe8SLucas Mateus Castro (alqotel) break; 5685118ebe8SLucas Mateus Castro (alqotel) } 5695118ebe8SLucas Mateus Castro (alqotel) 5705118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < env->nb_BATs; i++) { 5715118ebe8SLucas Mateus Castro (alqotel) BATu = &BATut[i]; 5725118ebe8SLucas Mateus Castro (alqotel) BATl = &BATlt[i]; 5735118ebe8SLucas Mateus Castro (alqotel) BEPIu = *BATu & 0xF0000000; 5745118ebe8SLucas Mateus Castro (alqotel) BEPIl = *BATu & 0x0FFE0000; 5755118ebe8SLucas Mateus Castro (alqotel) bl = (*BATu & 0x00001FFC) << 15; 5765118ebe8SLucas Mateus Castro (alqotel) qemu_printf("%s BAT%d BATu " TARGET_FMT_lx 5775118ebe8SLucas Mateus Castro (alqotel) " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " " 5785118ebe8SLucas Mateus Castro (alqotel) TARGET_FMT_lx " " TARGET_FMT_lx "\n", 5795118ebe8SLucas Mateus Castro (alqotel) type == ACCESS_CODE ? "code" : "data", i, 5805118ebe8SLucas Mateus Castro (alqotel) *BATu, *BATl, BEPIu, BEPIl, bl); 5815118ebe8SLucas Mateus Castro (alqotel) } 5825118ebe8SLucas Mateus Castro (alqotel) } 5835118ebe8SLucas Mateus Castro (alqotel) 5845118ebe8SLucas Mateus Castro (alqotel) static void mmu6xx_dump_mmu(CPUPPCState *env) 5855118ebe8SLucas Mateus Castro (alqotel) { 5865118ebe8SLucas Mateus Castro (alqotel) PowerPCCPU *cpu = env_archcpu(env); 5875118ebe8SLucas Mateus Castro (alqotel) ppc6xx_tlb_t *tlb; 5885118ebe8SLucas Mateus Castro (alqotel) target_ulong sr; 5895118ebe8SLucas Mateus Castro (alqotel) int type, way, entry, i; 5905118ebe8SLucas Mateus Castro (alqotel) 5915118ebe8SLucas Mateus Castro (alqotel) qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu)); 5925118ebe8SLucas Mateus Castro (alqotel) qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu)); 5935118ebe8SLucas Mateus Castro (alqotel) 5945118ebe8SLucas Mateus Castro (alqotel) qemu_printf("\nSegment registers:\n"); 5955118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < 32; i++) { 5965118ebe8SLucas Mateus Castro (alqotel) sr = env->sr[i]; 5975118ebe8SLucas Mateus Castro (alqotel) if (sr & 0x80000000) { 5985118ebe8SLucas Mateus Castro (alqotel) qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x " 5995118ebe8SLucas Mateus Castro (alqotel) "CNTLR_SPEC=0x%05x\n", i, 6005118ebe8SLucas Mateus Castro (alqotel) sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0, 6015118ebe8SLucas Mateus Castro (alqotel) sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF), 6025118ebe8SLucas Mateus Castro (alqotel) (uint32_t)(sr & 0xFFFFF)); 6035118ebe8SLucas Mateus Castro (alqotel) } else { 6045118ebe8SLucas Mateus Castro (alqotel) qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i, 6055118ebe8SLucas Mateus Castro (alqotel) sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0, 6065118ebe8SLucas Mateus Castro (alqotel) sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0, 6075118ebe8SLucas Mateus Castro (alqotel) (uint32_t)(sr & 0x00FFFFFF)); 6085118ebe8SLucas Mateus Castro (alqotel) } 6095118ebe8SLucas Mateus Castro (alqotel) } 6105118ebe8SLucas Mateus Castro (alqotel) 6115118ebe8SLucas Mateus Castro (alqotel) qemu_printf("\nBATs:\n"); 6125118ebe8SLucas Mateus Castro (alqotel) mmu6xx_dump_BATs(env, ACCESS_INT); 6135118ebe8SLucas Mateus Castro (alqotel) mmu6xx_dump_BATs(env, ACCESS_CODE); 6145118ebe8SLucas Mateus Castro (alqotel) 6155118ebe8SLucas Mateus Castro (alqotel) qemu_printf("\nTLBs [EPN EPN + SIZE]\n"); 6165118ebe8SLucas Mateus Castro (alqotel) for (type = 0; type < 2; type++) { 6175118ebe8SLucas Mateus Castro (alqotel) for (way = 0; way < env->nb_ways; way++) { 6185118ebe8SLucas Mateus Castro (alqotel) for (entry = env->nb_tlb * type + env->tlb_per_way * way; 6195118ebe8SLucas Mateus Castro (alqotel) entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1)); 6205118ebe8SLucas Mateus Castro (alqotel) entry++) { 6215118ebe8SLucas Mateus Castro (alqotel) 6225118ebe8SLucas Mateus Castro (alqotel) tlb = &env->tlb.tlb6[entry]; 6235118ebe8SLucas Mateus Castro (alqotel) qemu_printf("%s TLB %02d/%02d way:%d %s [" 6245118ebe8SLucas Mateus Castro (alqotel) TARGET_FMT_lx " " TARGET_FMT_lx "]\n", 6255118ebe8SLucas Mateus Castro (alqotel) type ? "code" : "data", entry % env->nb_tlb, 6265118ebe8SLucas Mateus Castro (alqotel) env->nb_tlb, way, 6275118ebe8SLucas Mateus Castro (alqotel) pte_is_valid(tlb->pte0) ? "valid" : "inval", 6285118ebe8SLucas Mateus Castro (alqotel) tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE); 6295118ebe8SLucas Mateus Castro (alqotel) } 6305118ebe8SLucas Mateus Castro (alqotel) } 6315118ebe8SLucas Mateus Castro (alqotel) } 6325118ebe8SLucas Mateus Castro (alqotel) } 6335118ebe8SLucas Mateus Castro (alqotel) 6345118ebe8SLucas Mateus Castro (alqotel) void dump_mmu(CPUPPCState *env) 6355118ebe8SLucas Mateus Castro (alqotel) { 6365118ebe8SLucas Mateus Castro (alqotel) switch (env->mmu_model) { 6375118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_BOOKE: 6385118ebe8SLucas Mateus Castro (alqotel) mmubooke_dump_mmu(env); 6395118ebe8SLucas Mateus Castro (alqotel) break; 6405118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_BOOKE206: 6415118ebe8SLucas Mateus Castro (alqotel) mmubooke206_dump_mmu(env); 6425118ebe8SLucas Mateus Castro (alqotel) break; 6435118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_SOFT_6xx: 6445118ebe8SLucas Mateus Castro (alqotel) mmu6xx_dump_mmu(env); 6455118ebe8SLucas Mateus Castro (alqotel) break; 6465118ebe8SLucas Mateus Castro (alqotel) #if defined(TARGET_PPC64) 6475118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_64B: 6485118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_2_03: 6495118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_2_06: 6505118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_2_07: 6515118ebe8SLucas Mateus Castro (alqotel) dump_slb(env_archcpu(env)); 6525118ebe8SLucas Mateus Castro (alqotel) break; 6535118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_3_00: 6545118ebe8SLucas Mateus Castro (alqotel) if (ppc64_v3_radix(env_archcpu(env))) { 6555118ebe8SLucas Mateus Castro (alqotel) qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n", 6565118ebe8SLucas Mateus Castro (alqotel) __func__); 6575118ebe8SLucas Mateus Castro (alqotel) } else { 6585118ebe8SLucas Mateus Castro (alqotel) dump_slb(env_archcpu(env)); 6595118ebe8SLucas Mateus Castro (alqotel) } 6605118ebe8SLucas Mateus Castro (alqotel) break; 6615118ebe8SLucas Mateus Castro (alqotel) #endif 6625118ebe8SLucas Mateus Castro (alqotel) default: 6635118ebe8SLucas Mateus Castro (alqotel) qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__); 6645118ebe8SLucas Mateus Castro (alqotel) } 6655118ebe8SLucas Mateus Castro (alqotel) } 6665118ebe8SLucas Mateus Castro (alqotel) 667ba91e5d0SBALATON Zoltan 668c29f808aSBALATON Zoltan static bool ppc_real_mode_xlate(PowerPCCPU *cpu, vaddr eaddr, 669c29f808aSBALATON Zoltan MMUAccessType access_type, 670c29f808aSBALATON Zoltan hwaddr *raddrp, int *psizep, int *protp) 671c29f808aSBALATON Zoltan { 672c29f808aSBALATON Zoltan CPUPPCState *env = &cpu->env; 673c29f808aSBALATON Zoltan 674c29f808aSBALATON Zoltan if (access_type == MMU_INST_FETCH ? !FIELD_EX64(env->msr, MSR, IR) 675c29f808aSBALATON Zoltan : !FIELD_EX64(env->msr, MSR, DR)) { 676c29f808aSBALATON Zoltan *raddrp = eaddr; 677c29f808aSBALATON Zoltan *protp = PAGE_RWX; 678c29f808aSBALATON Zoltan *psizep = TARGET_PAGE_BITS; 679c29f808aSBALATON Zoltan return true; 680c29f808aSBALATON Zoltan } else if (env->mmu_model == POWERPC_MMU_REAL) { 681c29f808aSBALATON Zoltan cpu_abort(CPU(cpu), "PowerPC in real mode shold not do translation\n"); 682c29f808aSBALATON Zoltan } 683c29f808aSBALATON Zoltan return false; 684c29f808aSBALATON Zoltan } 685c29f808aSBALATON Zoltan 68658b01325SBALATON Zoltan static bool ppc_40x_xlate(PowerPCCPU *cpu, vaddr eaddr, 68758b01325SBALATON Zoltan MMUAccessType access_type, 68858b01325SBALATON Zoltan hwaddr *raddrp, int *psizep, int *protp, 68958b01325SBALATON Zoltan int mmu_idx, bool guest_visible) 69058b01325SBALATON Zoltan { 69158b01325SBALATON Zoltan CPUState *cs = CPU(cpu); 69258b01325SBALATON Zoltan CPUPPCState *env = &cpu->env; 69358b01325SBALATON Zoltan int ret; 69458b01325SBALATON Zoltan 69558b01325SBALATON Zoltan if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) { 69658b01325SBALATON Zoltan return true; 69758b01325SBALATON Zoltan } 69858b01325SBALATON Zoltan 69958b01325SBALATON Zoltan ret = mmu40x_get_physical_address(env, raddrp, protp, eaddr, access_type); 70058b01325SBALATON Zoltan if (ret == 0) { 70158b01325SBALATON Zoltan *psizep = TARGET_PAGE_BITS; 70258b01325SBALATON Zoltan return true; 70358b01325SBALATON Zoltan } else if (!guest_visible) { 70458b01325SBALATON Zoltan return false; 70558b01325SBALATON Zoltan } 70658b01325SBALATON Zoltan 70758b01325SBALATON Zoltan log_cpu_state_mask(CPU_LOG_MMU, cs, 0); 70858b01325SBALATON Zoltan if (access_type == MMU_INST_FETCH) { 70958b01325SBALATON Zoltan switch (ret) { 71058b01325SBALATON Zoltan case -1: 71158b01325SBALATON Zoltan /* No matches in page tables or TLB */ 71258b01325SBALATON Zoltan cs->exception_index = POWERPC_EXCP_ITLB; 71358b01325SBALATON Zoltan env->error_code = 0; 71458b01325SBALATON Zoltan env->spr[SPR_40x_DEAR] = eaddr; 71558b01325SBALATON Zoltan env->spr[SPR_40x_ESR] = 0x00000000; 71658b01325SBALATON Zoltan break; 71758b01325SBALATON Zoltan case -2: 71858b01325SBALATON Zoltan /* Access rights violation */ 71958b01325SBALATON Zoltan cs->exception_index = POWERPC_EXCP_ISI; 72058b01325SBALATON Zoltan env->error_code = 0x08000000; 72158b01325SBALATON Zoltan break; 72258b01325SBALATON Zoltan default: 72358b01325SBALATON Zoltan g_assert_not_reached(); 72458b01325SBALATON Zoltan } 72558b01325SBALATON Zoltan } else { 72658b01325SBALATON Zoltan switch (ret) { 72758b01325SBALATON Zoltan case -1: 72858b01325SBALATON Zoltan /* No matches in page tables or TLB */ 72958b01325SBALATON Zoltan cs->exception_index = POWERPC_EXCP_DTLB; 73058b01325SBALATON Zoltan env->error_code = 0; 73158b01325SBALATON Zoltan env->spr[SPR_40x_DEAR] = eaddr; 73258b01325SBALATON Zoltan if (access_type == MMU_DATA_STORE) { 73358b01325SBALATON Zoltan env->spr[SPR_40x_ESR] = 0x00800000; 73458b01325SBALATON Zoltan } else { 73558b01325SBALATON Zoltan env->spr[SPR_40x_ESR] = 0x00000000; 73658b01325SBALATON Zoltan } 73758b01325SBALATON Zoltan break; 73858b01325SBALATON Zoltan case -2: 73958b01325SBALATON Zoltan /* Access rights violation */ 74058b01325SBALATON Zoltan cs->exception_index = POWERPC_EXCP_DSI; 74158b01325SBALATON Zoltan env->error_code = 0; 74258b01325SBALATON Zoltan env->spr[SPR_40x_DEAR] = eaddr; 74358b01325SBALATON Zoltan if (access_type == MMU_DATA_STORE) { 74458b01325SBALATON Zoltan env->spr[SPR_40x_ESR] |= 0x00800000; 74558b01325SBALATON Zoltan } 74658b01325SBALATON Zoltan break; 74758b01325SBALATON Zoltan default: 74858b01325SBALATON Zoltan g_assert_not_reached(); 74958b01325SBALATON Zoltan } 75058b01325SBALATON Zoltan } 75158b01325SBALATON Zoltan return false; 75258b01325SBALATON Zoltan } 75358b01325SBALATON Zoltan 7546b9ea7f3SBALATON Zoltan static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr, 7555118ebe8SLucas Mateus Castro (alqotel) MMUAccessType access_type, 7565118ebe8SLucas Mateus Castro (alqotel) hwaddr *raddrp, int *psizep, int *protp, 7575118ebe8SLucas Mateus Castro (alqotel) int mmu_idx, bool guest_visible) 7585118ebe8SLucas Mateus Castro (alqotel) { 7595118ebe8SLucas Mateus Castro (alqotel) CPUState *cs = CPU(cpu); 7605118ebe8SLucas Mateus Castro (alqotel) CPUPPCState *env = &cpu->env; 7615118ebe8SLucas Mateus Castro (alqotel) mmu_ctx_t ctx; 762*f6f8838bSBALATON Zoltan hwaddr hash = 0; /* init to 0 to avoid used uninit warning */ 763*f6f8838bSBALATON Zoltan int type, ret; 7645118ebe8SLucas Mateus Castro (alqotel) 765c29f808aSBALATON Zoltan if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) { 766c29f808aSBALATON Zoltan return true; 767c29f808aSBALATON Zoltan } 768c29f808aSBALATON Zoltan 7695118ebe8SLucas Mateus Castro (alqotel) if (access_type == MMU_INST_FETCH) { 7705118ebe8SLucas Mateus Castro (alqotel) /* code access */ 7715118ebe8SLucas Mateus Castro (alqotel) type = ACCESS_CODE; 7725118ebe8SLucas Mateus Castro (alqotel) } else if (guest_visible) { 7735118ebe8SLucas Mateus Castro (alqotel) /* data access */ 7745118ebe8SLucas Mateus Castro (alqotel) type = env->access_type; 7755118ebe8SLucas Mateus Castro (alqotel) } else { 7765118ebe8SLucas Mateus Castro (alqotel) type = ACCESS_INT; 7775118ebe8SLucas Mateus Castro (alqotel) } 7785118ebe8SLucas Mateus Castro (alqotel) 7796b9ea7f3SBALATON Zoltan ctx.prot = 0; 780*f6f8838bSBALATON Zoltan ret = mmu6xx_get_physical_address(env, &ctx, eaddr, &hash, 781*f6f8838bSBALATON Zoltan access_type, type); 7825118ebe8SLucas Mateus Castro (alqotel) if (ret == 0) { 7835118ebe8SLucas Mateus Castro (alqotel) *raddrp = ctx.raddr; 7845118ebe8SLucas Mateus Castro (alqotel) *protp = ctx.prot; 7855118ebe8SLucas Mateus Castro (alqotel) *psizep = TARGET_PAGE_BITS; 7865118ebe8SLucas Mateus Castro (alqotel) return true; 7879e9ca54cSBALATON Zoltan } else if (!guest_visible) { 7889e9ca54cSBALATON Zoltan return false; 7895118ebe8SLucas Mateus Castro (alqotel) } 7905118ebe8SLucas Mateus Castro (alqotel) 79156964585SCédric Le Goater log_cpu_state_mask(CPU_LOG_MMU, cs, 0); 7925118ebe8SLucas Mateus Castro (alqotel) if (type == ACCESS_CODE) { 7935118ebe8SLucas Mateus Castro (alqotel) switch (ret) { 7945118ebe8SLucas Mateus Castro (alqotel) case -1: 7955118ebe8SLucas Mateus Castro (alqotel) /* No matches in page tables or TLB */ 7965118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_IFTLB; 7975118ebe8SLucas Mateus Castro (alqotel) env->error_code = 1 << 18; 7985118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_IMISS] = eaddr; 7995118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem; 8005118ebe8SLucas Mateus Castro (alqotel) goto tlb_miss; 8015118ebe8SLucas Mateus Castro (alqotel) case -2: 8025118ebe8SLucas Mateus Castro (alqotel) /* Access rights violation */ 8035118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_ISI; 8045118ebe8SLucas Mateus Castro (alqotel) env->error_code = 0x08000000; 8055118ebe8SLucas Mateus Castro (alqotel) break; 8065118ebe8SLucas Mateus Castro (alqotel) case -3: 8075118ebe8SLucas Mateus Castro (alqotel) /* No execute protection violation */ 8085118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_ISI; 809ba91e5d0SBALATON Zoltan env->error_code = 0x10000000; 8105118ebe8SLucas Mateus Castro (alqotel) break; 8115118ebe8SLucas Mateus Castro (alqotel) case -4: 8125118ebe8SLucas Mateus Castro (alqotel) /* Direct store exception */ 8135118ebe8SLucas Mateus Castro (alqotel) /* No code fetch is allowed in direct-store areas */ 8145118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_ISI; 8155118ebe8SLucas Mateus Castro (alqotel) env->error_code = 0x10000000; 8165118ebe8SLucas Mateus Castro (alqotel) break; 8175118ebe8SLucas Mateus Castro (alqotel) } 8185118ebe8SLucas Mateus Castro (alqotel) } else { 8195118ebe8SLucas Mateus Castro (alqotel) switch (ret) { 8205118ebe8SLucas Mateus Castro (alqotel) case -1: 8215118ebe8SLucas Mateus Castro (alqotel) /* No matches in page tables or TLB */ 8225118ebe8SLucas Mateus Castro (alqotel) if (access_type == MMU_DATA_STORE) { 8235118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_DSTLB; 8245118ebe8SLucas Mateus Castro (alqotel) env->error_code = 1 << 16; 8255118ebe8SLucas Mateus Castro (alqotel) } else { 8265118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_DLTLB; 8275118ebe8SLucas Mateus Castro (alqotel) env->error_code = 0; 8285118ebe8SLucas Mateus Castro (alqotel) } 8295118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DMISS] = eaddr; 8305118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem; 8315118ebe8SLucas Mateus Castro (alqotel) tlb_miss: 8325118ebe8SLucas Mateus Castro (alqotel) env->error_code |= ctx.key << 19; 8335118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) + 834*f6f8838bSBALATON Zoltan get_pteg_offset32(cpu, hash); 8355118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) + 836*f6f8838bSBALATON Zoltan get_pteg_offset32(cpu, ~hash); 8375118ebe8SLucas Mateus Castro (alqotel) break; 8385118ebe8SLucas Mateus Castro (alqotel) case -2: 8395118ebe8SLucas Mateus Castro (alqotel) /* Access rights violation */ 8405118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_DSI; 8415118ebe8SLucas Mateus Castro (alqotel) env->error_code = 0; 8425118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DAR] = eaddr; 8435118ebe8SLucas Mateus Castro (alqotel) if (access_type == MMU_DATA_STORE) { 8445118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DSISR] = 0x0A000000; 8455118ebe8SLucas Mateus Castro (alqotel) } else { 8465118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DSISR] = 0x08000000; 8475118ebe8SLucas Mateus Castro (alqotel) } 8485118ebe8SLucas Mateus Castro (alqotel) break; 8495118ebe8SLucas Mateus Castro (alqotel) case -4: 8505118ebe8SLucas Mateus Castro (alqotel) /* Direct store exception */ 8515118ebe8SLucas Mateus Castro (alqotel) switch (type) { 8525118ebe8SLucas Mateus Castro (alqotel) case ACCESS_FLOAT: 8535118ebe8SLucas Mateus Castro (alqotel) /* Floating point load/store */ 8545118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_ALIGN; 8555118ebe8SLucas Mateus Castro (alqotel) env->error_code = POWERPC_EXCP_ALIGN_FP; 8565118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DAR] = eaddr; 8575118ebe8SLucas Mateus Castro (alqotel) break; 8585118ebe8SLucas Mateus Castro (alqotel) case ACCESS_RES: 8595118ebe8SLucas Mateus Castro (alqotel) /* lwarx, ldarx or stwcx. */ 8605118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_DSI; 8615118ebe8SLucas Mateus Castro (alqotel) env->error_code = 0; 8625118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DAR] = eaddr; 8635118ebe8SLucas Mateus Castro (alqotel) if (access_type == MMU_DATA_STORE) { 8645118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DSISR] = 0x06000000; 8655118ebe8SLucas Mateus Castro (alqotel) } else { 8665118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DSISR] = 0x04000000; 8675118ebe8SLucas Mateus Castro (alqotel) } 8685118ebe8SLucas Mateus Castro (alqotel) break; 8695118ebe8SLucas Mateus Castro (alqotel) case ACCESS_EXT: 8705118ebe8SLucas Mateus Castro (alqotel) /* eciwx or ecowx */ 8715118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_DSI; 8725118ebe8SLucas Mateus Castro (alqotel) env->error_code = 0; 8735118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DAR] = eaddr; 8745118ebe8SLucas Mateus Castro (alqotel) if (access_type == MMU_DATA_STORE) { 8755118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DSISR] = 0x06100000; 8765118ebe8SLucas Mateus Castro (alqotel) } else { 8775118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DSISR] = 0x04100000; 8785118ebe8SLucas Mateus Castro (alqotel) } 8795118ebe8SLucas Mateus Castro (alqotel) break; 8805118ebe8SLucas Mateus Castro (alqotel) default: 8815118ebe8SLucas Mateus Castro (alqotel) printf("DSI: invalid exception (%d)\n", ret); 8825118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_PROGRAM; 8839e9ca54cSBALATON Zoltan env->error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL; 8845118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DAR] = eaddr; 8855118ebe8SLucas Mateus Castro (alqotel) break; 8865118ebe8SLucas Mateus Castro (alqotel) } 8875118ebe8SLucas Mateus Castro (alqotel) break; 8885118ebe8SLucas Mateus Castro (alqotel) } 8895118ebe8SLucas Mateus Castro (alqotel) } 8905118ebe8SLucas Mateus Castro (alqotel) return false; 8915118ebe8SLucas Mateus Castro (alqotel) } 8925118ebe8SLucas Mateus Castro (alqotel) 8935118ebe8SLucas Mateus Castro (alqotel) /*****************************************************************************/ 8945118ebe8SLucas Mateus Castro (alqotel) 8955118ebe8SLucas Mateus Castro (alqotel) bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, 8965118ebe8SLucas Mateus Castro (alqotel) hwaddr *raddrp, int *psizep, int *protp, 8975118ebe8SLucas Mateus Castro (alqotel) int mmu_idx, bool guest_visible) 8985118ebe8SLucas Mateus Castro (alqotel) { 8995118ebe8SLucas Mateus Castro (alqotel) switch (cpu->env.mmu_model) { 9005118ebe8SLucas Mateus Castro (alqotel) #if defined(TARGET_PPC64) 9015118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_3_00: 9025118ebe8SLucas Mateus Castro (alqotel) if (ppc64_v3_radix(cpu)) { 9035118ebe8SLucas Mateus Castro (alqotel) return ppc_radix64_xlate(cpu, eaddr, access_type, raddrp, 9045118ebe8SLucas Mateus Castro (alqotel) psizep, protp, mmu_idx, guest_visible); 9055118ebe8SLucas Mateus Castro (alqotel) } 9065118ebe8SLucas Mateus Castro (alqotel) /* fall through */ 9075118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_64B: 9085118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_2_03: 9095118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_2_06: 9105118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_2_07: 9115118ebe8SLucas Mateus Castro (alqotel) return ppc_hash64_xlate(cpu, eaddr, access_type, 9125118ebe8SLucas Mateus Castro (alqotel) raddrp, psizep, protp, mmu_idx, guest_visible); 9135118ebe8SLucas Mateus Castro (alqotel) #endif 9145118ebe8SLucas Mateus Castro (alqotel) 9155118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_32B: 9165118ebe8SLucas Mateus Castro (alqotel) return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp, 9175118ebe8SLucas Mateus Castro (alqotel) psizep, protp, mmu_idx, guest_visible); 918ba91e5d0SBALATON Zoltan case POWERPC_MMU_BOOKE: 919ba91e5d0SBALATON Zoltan case POWERPC_MMU_BOOKE206: 920ba91e5d0SBALATON Zoltan return ppc_booke_xlate(cpu, eaddr, access_type, raddrp, 921ba91e5d0SBALATON Zoltan psizep, protp, mmu_idx, guest_visible); 92258b01325SBALATON Zoltan case POWERPC_MMU_SOFT_4xx: 92358b01325SBALATON Zoltan return ppc_40x_xlate(cpu, eaddr, access_type, raddrp, 92458b01325SBALATON Zoltan psizep, protp, mmu_idx, guest_visible); 9256b9ea7f3SBALATON Zoltan case POWERPC_MMU_SOFT_6xx: 9266b9ea7f3SBALATON Zoltan return ppc_6xx_xlate(cpu, eaddr, access_type, raddrp, 9276b9ea7f3SBALATON Zoltan psizep, protp, mmu_idx, guest_visible); 928c29f808aSBALATON Zoltan case POWERPC_MMU_REAL: 929c29f808aSBALATON Zoltan return ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, 930c29f808aSBALATON Zoltan protp); 931cfd5c128SBALATON Zoltan case POWERPC_MMU_MPC8xx: 932cfd5c128SBALATON Zoltan cpu_abort(env_cpu(&cpu->env), "MPC8xx MMU model is not implemented\n"); 9335118ebe8SLucas Mateus Castro (alqotel) default: 9346b9ea7f3SBALATON Zoltan cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n"); 9355118ebe8SLucas Mateus Castro (alqotel) } 9365118ebe8SLucas Mateus Castro (alqotel) } 9375118ebe8SLucas Mateus Castro (alqotel) 9385118ebe8SLucas Mateus Castro (alqotel) hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) 9395118ebe8SLucas Mateus Castro (alqotel) { 9405118ebe8SLucas Mateus Castro (alqotel) PowerPCCPU *cpu = POWERPC_CPU(cs); 9415118ebe8SLucas Mateus Castro (alqotel) hwaddr raddr; 9425118ebe8SLucas Mateus Castro (alqotel) int s, p; 9435118ebe8SLucas Mateus Castro (alqotel) 9445118ebe8SLucas Mateus Castro (alqotel) /* 9455118ebe8SLucas Mateus Castro (alqotel) * Some MMUs have separate TLBs for code and data. If we only 9465118ebe8SLucas Mateus Castro (alqotel) * try an MMU_DATA_LOAD, we may not be able to read instructions 9475118ebe8SLucas Mateus Castro (alqotel) * mapped by code TLBs, so we also try a MMU_INST_FETCH. 9485118ebe8SLucas Mateus Castro (alqotel) */ 9495118ebe8SLucas Mateus Castro (alqotel) if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p, 950fb00f730SRichard Henderson ppc_env_mmu_index(&cpu->env, false), false) || 9515118ebe8SLucas Mateus Castro (alqotel) ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p, 952fb00f730SRichard Henderson ppc_env_mmu_index(&cpu->env, true), false)) { 9535118ebe8SLucas Mateus Castro (alqotel) return raddr & TARGET_PAGE_MASK; 9545118ebe8SLucas Mateus Castro (alqotel) } 9555118ebe8SLucas Mateus Castro (alqotel) return -1; 9565118ebe8SLucas Mateus Castro (alqotel) } 957