xref: /qemu/target/ppc/mmu_common.c (revision ffd5a60e9b67e14f7bac7ea29300ea46a944e508)
1 /*
2  *  PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU.
3  *
4  *  Copyright (c) 2003-2007 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "qemu/osdep.h"
21 #include "qemu/units.h"
22 #include "cpu.h"
23 #include "system/kvm.h"
24 #include "kvm_ppc.h"
25 #include "mmu-hash64.h"
26 #include "mmu-hash32.h"
27 #include "exec/exec-all.h"
28 #include "exec/page-protection.h"
29 #include "exec/target_page.h"
30 #include "exec/log.h"
31 #include "helper_regs.h"
32 #include "qemu/error-report.h"
33 #include "qemu/qemu-print.h"
34 #include "internal.h"
35 #include "mmu-book3s-v3.h"
36 #include "mmu-radix64.h"
37 #include "mmu-booke.h"
38 
39 /* #define DUMP_PAGE_TABLES */
40 
41 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
42 {
43     PowerPCCPU *cpu = env_archcpu(env);
44     qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
45     assert(!cpu->env.has_hv_mode || !cpu->vhyp);
46 #if defined(TARGET_PPC64)
47     if (mmu_is_64bit(env->mmu_model)) {
48         target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
49         target_ulong htabsize = value & SDR_64_HTABSIZE;
50 
51         if (value & ~sdr_mask) {
52             qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx
53                      " set in SDR1", value & ~sdr_mask);
54             value &= sdr_mask;
55         }
56         if (htabsize > 28) {
57             qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx
58                      " stored in SDR1", htabsize);
59             return;
60         }
61     }
62 #endif /* defined(TARGET_PPC64) */
63     /* FIXME: Should check for valid HTABMASK values in 32-bit case */
64     env->spr[SPR_SDR1] = value;
65 }
66 
67 /*****************************************************************************/
68 /* PowerPC MMU emulation */
69 
70 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
71                                     int way, int is_code)
72 {
73     int nr;
74 
75     /* Select TLB num in a way from address */
76     nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
77     /* Select TLB way */
78     nr += env->tlb_per_way * way;
79     /* 6xx has separate TLBs for instructions and data */
80     if (is_code) {
81         nr += env->nb_tlb;
82     }
83 
84     return nr;
85 }
86 
87 /* Software driven TLB helpers */
88 
89 static int ppc6xx_tlb_check(CPUPPCState *env, hwaddr *raddr, int *prot,
90                             target_ulong eaddr, MMUAccessType access_type,
91                             target_ulong ptem, bool key, bool nx)
92 {
93     ppc6xx_tlb_t *tlb;
94     target_ulong *pte1p;
95     int nr, best, way, ret;
96     bool is_code = (access_type == MMU_INST_FETCH);
97 
98     /* Initialize real address with an invalid value */
99     *raddr = (hwaddr)-1ULL;
100     best = -1;
101     ret = -1; /* No TLB found */
102     for (way = 0; way < env->nb_ways; way++) {
103         nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
104         tlb = &env->tlb.tlb6[nr];
105         /* This test "emulates" the PTE index match for hardware TLBs */
106         if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
107             qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx
108                           " " TARGET_FMT_lx "] <> " TARGET_FMT_lx "\n",
109                           nr, env->nb_tlb,
110                           pte_is_valid(tlb->pte0) ? "valid" : "inval",
111                           tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
112             continue;
113         }
114         qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s " TARGET_FMT_lx " <> "
115                       TARGET_FMT_lx " " TARGET_FMT_lx " %c %c\n",
116                       nr, env->nb_tlb,
117                       pte_is_valid(tlb->pte0) ? "valid" : "inval",
118                       tlb->EPN, eaddr, tlb->pte1,
119                       access_type == MMU_DATA_STORE ? 'S' : 'L',
120                       access_type == MMU_INST_FETCH ? 'I' : 'D');
121         /* Check validity and table match */
122         if (!pte_is_valid(tlb->pte0) || ((tlb->pte0 >> 6) & 1) != 0 ||
123             (tlb->pte0 & PTE_PTEM_MASK) != ptem) {
124             continue;
125         }
126         /* all matches should have equal RPN, WIMG & PP */
127         if (*raddr != (hwaddr)-1ULL &&
128             (*raddr & PTE_CHECK_MASK) != (tlb->pte1 & PTE_CHECK_MASK)) {
129             qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
130             /* TLB inconsistency */
131             continue;
132         }
133         /* Keep the matching PTE information */
134         best = nr;
135         *raddr = tlb->pte1;
136         *prot = ppc_hash32_prot(key, tlb->pte1 & HPTE32_R_PP, nx);
137         if (check_prot_access_type(*prot, access_type)) {
138             qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
139             ret = 0;
140             break;
141         } else {
142             qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
143             ret = -2;
144         }
145     }
146     if (best != -1) {
147         qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx
148                       " prot=%01x ret=%d\n",
149                       *raddr & TARGET_PAGE_MASK, *prot, ret);
150         /* Update page flags */
151         pte1p = &env->tlb.tlb6[best].pte1;
152         *pte1p |= 0x00000100; /* Update accessed flag */
153         if (!(*pte1p & 0x00000080)) {
154             if (access_type == MMU_DATA_STORE && ret == 0) {
155                 /* Update changed flag */
156                 *pte1p |= 0x00000080;
157             } else {
158                 /* Force page fault for first write access */
159                 *prot &= ~PAGE_WRITE;
160             }
161         }
162     }
163     if (ret == -1) {
164         int r = is_code ? SPR_ICMP : SPR_DCMP;
165         env->spr[r] = ptem;
166     }
167 #if defined(DUMP_PAGE_TABLES)
168     if (qemu_loglevel_mask(CPU_LOG_MMU)) {
169         CPUState *cs = env_cpu(env);
170         hwaddr base = ppc_hash32_hpt_base(env_archcpu(env));
171         hwaddr len = ppc_hash32_hpt_mask(env_archcpu(env)) + 0x80;
172         uint32_t a0, a1, a2, a3;
173 
174         qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n",
175                  base, len);
176         for (hwaddr curaddr = base; curaddr < base + len; curaddr += 16) {
177             a0 = ldl_phys(cs->as, curaddr);
178             a1 = ldl_phys(cs->as, curaddr + 4);
179             a2 = ldl_phys(cs->as, curaddr + 8);
180             a3 = ldl_phys(cs->as, curaddr + 12);
181             if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
182                 qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
183                          curaddr, a0, a1, a2, a3);
184             }
185         }
186     }
187 #endif
188     return ret;
189 }
190 
191 static int get_bat_6xx_tlb(CPUPPCState *env, hwaddr *raddr, int *prot,
192                            target_ulong eaddr, MMUAccessType access_type,
193                            bool pr)
194 {
195     target_ulong *BATlt, *BATut, *BATu, *BATl;
196     target_ulong BEPIl, BEPIu, bl;
197     int i, ret = -1;
198     bool ifetch = access_type == MMU_INST_FETCH;
199 
200     qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
201                   ifetch ? 'I' : 'D', eaddr);
202     if (ifetch) {
203         BATlt = env->IBAT[1];
204         BATut = env->IBAT[0];
205     } else {
206         BATlt = env->DBAT[1];
207         BATut = env->DBAT[0];
208     }
209     for (i = 0; i < env->nb_BATs; i++) {
210         BATu = &BATut[i];
211         BATl = &BATlt[i];
212         BEPIu = *BATu & BATU32_BEPIU;
213         BEPIl = *BATu & BATU32_BEPIL;
214         qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
215                       TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
216                       ifetch ? 'I' : 'D', i, eaddr, *BATu, *BATl);
217         bl = (*BATu & BATU32_BL) << 15;
218         if ((!pr && (*BATu & BATU32_VS)) || (pr && (*BATu & BATU32_VP))) {
219             if ((eaddr & BATU32_BEPIU) == BEPIu &&
220                 ((eaddr & BATU32_BEPIL) & ~bl) == BEPIl) {
221                 /* Get physical address */
222                 *raddr = (*BATl & BATU32_BEPIU) |
223                     ((eaddr & BATU32_BEPIL & bl) | (*BATl & BATU32_BEPIL)) |
224                     (eaddr & 0x0001F000);
225                 /* Compute access rights */
226                 *prot = ppc_hash32_bat_prot(*BATu, *BATl);
227                 if (check_prot_access_type(*prot, access_type)) {
228                     qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " HWADDR_FMT_plx
229                                   " prot=%c%c\n", i, *raddr,
230                                   *prot & PAGE_READ ? 'R' : '-',
231                                   *prot & PAGE_WRITE ? 'W' : '-');
232                     ret = 0;
233                 } else {
234                     ret = -2;
235                 }
236                 break;
237             }
238         }
239     }
240     if (ret < 0) {
241         if (qemu_log_enabled()) {
242             qemu_log_mask(CPU_LOG_MMU, "no BAT match for "
243                           TARGET_FMT_lx ":\n", eaddr);
244             for (i = 0; i < 4; i++) {
245                 BATu = &BATut[i];
246                 BATl = &BATlt[i];
247                 BEPIu = *BATu & BATU32_BEPIU;
248                 BEPIl = *BATu & BATU32_BEPIL;
249                 bl = (*BATu & BATU32_BL) << 15;
250                 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx
251                               " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx
252                               "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " "
253                               TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D',
254                               i, eaddr, *BATu, *BATl, BEPIu, BEPIl, bl);
255             }
256         }
257     }
258     /* No hit */
259     return ret;
260 }
261 
262 static int mmu6xx_get_physical_address(CPUPPCState *env, hwaddr *raddr,
263                                        int *prot, target_ulong eaddr,
264                                        hwaddr *hashp, bool *keyp,
265                                        MMUAccessType access_type, int type)
266 {
267     PowerPCCPU *cpu = env_archcpu(env);
268     hwaddr hash;
269     target_ulong vsid, sr, pgidx, ptem;
270     bool key, ds, nx;
271     bool pr = FIELD_EX64(env->msr, MSR, PR);
272 
273     /* First try to find a BAT entry if there are any */
274     if (env->nb_BATs &&
275         get_bat_6xx_tlb(env, raddr, prot, eaddr, access_type, pr) == 0) {
276         return 0;
277     }
278 
279     /* Perform segment based translation when no BATs matched */
280     sr = env->sr[eaddr >> 28];
281     key = ppc_hash32_key(pr, sr);
282     *keyp = key;
283     ds = sr & SR32_T;
284     nx = sr & SR32_NX;
285     vsid = sr & SR32_VSID;
286     qemu_log_mask(CPU_LOG_MMU,
287                   "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
288                   " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
289                   " ir=%d dr=%d pr=%d %d t=%d\n",
290                   eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr,
291                   (int)FIELD_EX64(env->msr, MSR, IR),
292                   (int)FIELD_EX64(env->msr, MSR, DR), pr ? 1 : 0,
293                   access_type == MMU_DATA_STORE, type);
294     pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS;
295     hash = vsid ^ pgidx;
296     ptem = (vsid << 7) | (pgidx >> 10); /* Virtual segment ID | API */
297 
298     qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid "
299                   TARGET_FMT_lx "\n", key, ds, nx, vsid);
300     if (!ds) {
301         /* Check if instruction fetch is allowed, if needed */
302         if (type == ACCESS_CODE && nx) {
303             qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
304             return -3;
305         }
306         /* Page address translation */
307         qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
308                       HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
309                       ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
310         *hashp = hash;
311 
312         /* Software TLB search */
313         return ppc6xx_tlb_check(env, raddr, prot, eaddr,
314                                 access_type, ptem, key, nx);
315     }
316 
317     /* Direct-store segment : absolutely *BUGGY* for now */
318     qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
319     switch (type) {
320     case ACCESS_INT:
321         /* Integer load/store : only access allowed */
322         break;
323     case ACCESS_CACHE:
324         /*
325          * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
326          *
327          * Should make the instruction do no-op.  As it already do
328          * no-op, it's quite easy :-)
329          */
330         *raddr = eaddr;
331         return 0;
332     case ACCESS_CODE: /* No code fetch is allowed in direct-store areas */
333     case ACCESS_FLOAT: /* Floating point load/store */
334     case ACCESS_RES: /* lwarx, ldarx or srwcx. */
335     case ACCESS_EXT: /* eciwx or ecowx */
336         return -4;
337     }
338     if ((access_type == MMU_DATA_STORE || !key) &&
339         (access_type == MMU_DATA_LOAD || key)) {
340         *raddr = eaddr;
341         return 2;
342     }
343     return -2;
344 }
345 
346 static const char *book3e_tsize_to_str[32] = {
347     "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
348     "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
349     "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
350     "1T", "2T"
351 };
352 
353 static void mmubooke_dump_mmu(CPUPPCState *env)
354 {
355     ppcemb_tlb_t *entry;
356     int i;
357 
358 #ifdef CONFIG_KVM
359     if (kvm_enabled() && !env->kvm_sw_tlb) {
360         qemu_printf("Cannot access KVM TLB\n");
361         return;
362     }
363 #endif
364 
365     qemu_printf("\nTLB:\n");
366     qemu_printf("Effective          Physical           Size PID   Prot     "
367                 "Attr\n");
368 
369     entry = &env->tlb.tlbe[0];
370     for (i = 0; i < env->nb_tlb; i++, entry++) {
371         hwaddr ea, pa;
372         target_ulong mask;
373         uint64_t size = (uint64_t)entry->size;
374         char size_buf[20];
375 
376         /* Check valid flag */
377         if (!(entry->prot & PAGE_VALID)) {
378             continue;
379         }
380 
381         mask = ~(entry->size - 1);
382         ea = entry->EPN & mask;
383         pa = entry->RPN & mask;
384         /* Extend the physical address to 36 bits */
385         pa |= (hwaddr)(entry->RPN & 0xF) << 32;
386         if (size >= 1 * MiB) {
387             snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB);
388         } else {
389             snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB);
390         }
391         qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
392                     (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
393                     entry->prot, entry->attr);
394     }
395 
396 }
397 
398 static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset,
399                                      int tlbsize)
400 {
401     ppcmas_tlb_t *entry;
402     int i;
403 
404     qemu_printf("\nTLB%d:\n", tlbn);
405     qemu_printf("Effective          Physical           Size TID   TS SRWX"
406                 " URWX WIMGE U0123\n");
407 
408     entry = &env->tlb.tlbm[offset];
409     for (i = 0; i < tlbsize; i++, entry++) {
410         hwaddr ea, pa, size;
411         int tsize;
412 
413         if (!(entry->mas1 & MAS1_VALID)) {
414             continue;
415         }
416 
417         tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
418         size = 1024ULL << tsize;
419         ea = entry->mas2 & ~(size - 1);
420         pa = entry->mas7_3 & ~(size - 1);
421 
422         qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u  S%c%c%c"
423                     " U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
424                     (uint64_t)ea, (uint64_t)pa,
425                     book3e_tsize_to_str[tsize],
426                     (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
427                     (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
428                     entry->mas7_3 & MAS3_SR ? 'R' : '-',
429                     entry->mas7_3 & MAS3_SW ? 'W' : '-',
430                     entry->mas7_3 & MAS3_SX ? 'X' : '-',
431                     entry->mas7_3 & MAS3_UR ? 'R' : '-',
432                     entry->mas7_3 & MAS3_UW ? 'W' : '-',
433                     entry->mas7_3 & MAS3_UX ? 'X' : '-',
434                     entry->mas2 & MAS2_W ? 'W' : '-',
435                     entry->mas2 & MAS2_I ? 'I' : '-',
436                     entry->mas2 & MAS2_M ? 'M' : '-',
437                     entry->mas2 & MAS2_G ? 'G' : '-',
438                     entry->mas2 & MAS2_E ? 'E' : '-',
439                     entry->mas7_3 & MAS3_U0 ? '0' : '-',
440                     entry->mas7_3 & MAS3_U1 ? '1' : '-',
441                     entry->mas7_3 & MAS3_U2 ? '2' : '-',
442                     entry->mas7_3 & MAS3_U3 ? '3' : '-');
443     }
444 }
445 
446 static void mmubooke206_dump_mmu(CPUPPCState *env)
447 {
448     int offset = 0;
449     int i;
450 
451 #ifdef CONFIG_KVM
452     if (kvm_enabled() && !env->kvm_sw_tlb) {
453         qemu_printf("Cannot access KVM TLB\n");
454         return;
455     }
456 #endif
457 
458     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
459         int size = booke206_tlb_size(env, i);
460 
461         if (size == 0) {
462             continue;
463         }
464 
465         mmubooke206_dump_one_tlb(env, i, offset, size);
466         offset += size;
467     }
468 }
469 
470 static void mmu6xx_dump_BATs(CPUPPCState *env, int type)
471 {
472     target_ulong *BATlt, *BATut, *BATu, *BATl;
473     target_ulong BEPIl, BEPIu, bl;
474     int i;
475 
476     switch (type) {
477     case ACCESS_CODE:
478         BATlt = env->IBAT[1];
479         BATut = env->IBAT[0];
480         break;
481     default:
482         BATlt = env->DBAT[1];
483         BATut = env->DBAT[0];
484         break;
485     }
486 
487     for (i = 0; i < env->nb_BATs; i++) {
488         BATu = &BATut[i];
489         BATl = &BATlt[i];
490         BEPIu = *BATu & BATU32_BEPIU;
491         BEPIl = *BATu & BATU32_BEPIL;
492         bl = (*BATu & BATU32_BL) << 15;
493         qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
494                     " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
495                     TARGET_FMT_lx " " TARGET_FMT_lx "\n",
496                     type == ACCESS_CODE ? "code" : "data", i,
497                     *BATu, *BATl, BEPIu, BEPIl, bl);
498     }
499 }
500 
501 static void mmu6xx_dump_mmu(CPUPPCState *env)
502 {
503     PowerPCCPU *cpu = env_archcpu(env);
504     ppc6xx_tlb_t *tlb;
505     target_ulong sr;
506     int type, way, entry, i;
507 
508     qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu));
509     qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu));
510 
511     qemu_printf("\nSegment registers:\n");
512     for (i = 0; i < 32; i++) {
513         sr = env->sr[i];
514         if (sr & 0x80000000) {
515             qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
516                         "CNTLR_SPEC=0x%05x\n", i,
517                         sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
518                         sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF),
519                         (uint32_t)(sr & 0xFFFFF));
520         } else {
521             qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i,
522                         sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
523                         sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0,
524                         (uint32_t)(sr & 0x00FFFFFF));
525         }
526     }
527 
528     qemu_printf("\nBATs:\n");
529     mmu6xx_dump_BATs(env, ACCESS_INT);
530     mmu6xx_dump_BATs(env, ACCESS_CODE);
531 
532     qemu_printf("\nTLBs                       [EPN    EPN + SIZE]\n");
533     for (type = 0; type < 2; type++) {
534         for (way = 0; way < env->nb_ways; way++) {
535             for (entry = env->nb_tlb * type + env->tlb_per_way * way;
536                  entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1));
537                  entry++) {
538 
539                 tlb = &env->tlb.tlb6[entry];
540                 qemu_printf("%s TLB %02d/%02d way:%d %s ["
541                             TARGET_FMT_lx " " TARGET_FMT_lx "]\n",
542                             type ? "code" : "data", entry % env->nb_tlb,
543                             env->nb_tlb, way,
544                             pte_is_valid(tlb->pte0) ? "valid" : "inval",
545                             tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE);
546             }
547         }
548     }
549 }
550 
551 void dump_mmu(CPUPPCState *env)
552 {
553     switch (env->mmu_model) {
554     case POWERPC_MMU_BOOKE:
555         mmubooke_dump_mmu(env);
556         break;
557     case POWERPC_MMU_BOOKE206:
558         mmubooke206_dump_mmu(env);
559         break;
560     case POWERPC_MMU_SOFT_6xx:
561         mmu6xx_dump_mmu(env);
562         break;
563 #if defined(TARGET_PPC64)
564     case POWERPC_MMU_64B:
565     case POWERPC_MMU_2_03:
566     case POWERPC_MMU_2_06:
567     case POWERPC_MMU_2_07:
568         dump_slb(env_archcpu(env));
569         break;
570     case POWERPC_MMU_3_00:
571         if (ppc64_v3_radix(env_archcpu(env))) {
572             qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n",
573                           __func__);
574         } else {
575             dump_slb(env_archcpu(env));
576         }
577         break;
578 #endif
579     default:
580         qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
581     }
582 }
583 
584 
585 static bool ppc_real_mode_xlate(PowerPCCPU *cpu, vaddr eaddr,
586                                 MMUAccessType access_type,
587                                 hwaddr *raddrp, int *psizep, int *protp)
588 {
589     CPUPPCState *env = &cpu->env;
590 
591     if (access_type == MMU_INST_FETCH ? !FIELD_EX64(env->msr, MSR, IR)
592                                       : !FIELD_EX64(env->msr, MSR, DR)) {
593         *raddrp = eaddr;
594         *protp = PAGE_RWX;
595         *psizep = TARGET_PAGE_BITS;
596         return true;
597     } else if (env->mmu_model == POWERPC_MMU_REAL) {
598         cpu_abort(CPU(cpu), "PowerPC in real mode shold not do translation\n");
599     }
600     return false;
601 }
602 
603 static bool ppc_40x_xlate(PowerPCCPU *cpu, vaddr eaddr,
604                           MMUAccessType access_type,
605                           hwaddr *raddrp, int *psizep, int *protp,
606                           int mmu_idx, bool guest_visible)
607 {
608     CPUState *cs = CPU(cpu);
609     CPUPPCState *env = &cpu->env;
610     int ret;
611 
612     if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
613         return true;
614     }
615 
616     ret = mmu40x_get_physical_address(env, raddrp, protp, eaddr, access_type);
617     if (ret == 0) {
618         *psizep = TARGET_PAGE_BITS;
619         return true;
620     } else if (!guest_visible) {
621         return false;
622     }
623 
624     log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
625     if (access_type == MMU_INST_FETCH) {
626         switch (ret) {
627         case -1:
628             /* No matches in page tables or TLB */
629             cs->exception_index = POWERPC_EXCP_ITLB;
630             env->error_code = 0;
631             env->spr[SPR_40x_DEAR] = eaddr;
632             env->spr[SPR_40x_ESR] = 0x00000000;
633             break;
634         case -2:
635             /* Access rights violation */
636             cs->exception_index = POWERPC_EXCP_ISI;
637             env->error_code = 0x08000000;
638             break;
639         default:
640             g_assert_not_reached();
641         }
642     } else {
643         switch (ret) {
644         case -1:
645             /* No matches in page tables or TLB */
646             cs->exception_index = POWERPC_EXCP_DTLB;
647             env->error_code = 0;
648             env->spr[SPR_40x_DEAR] = eaddr;
649             if (access_type == MMU_DATA_STORE) {
650                 env->spr[SPR_40x_ESR] = 0x00800000;
651             } else {
652                 env->spr[SPR_40x_ESR] = 0x00000000;
653             }
654             break;
655         case -2:
656             /* Access rights violation */
657             cs->exception_index = POWERPC_EXCP_DSI;
658             env->error_code = 0;
659             env->spr[SPR_40x_DEAR] = eaddr;
660             if (access_type == MMU_DATA_STORE) {
661                 env->spr[SPR_40x_ESR] |= 0x00800000;
662             }
663             break;
664         default:
665             g_assert_not_reached();
666         }
667     }
668     return false;
669 }
670 
671 static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
672                           MMUAccessType access_type,
673                           hwaddr *raddrp, int *psizep, int *protp,
674                           int mmu_idx, bool guest_visible)
675 {
676     CPUState *cs = CPU(cpu);
677     CPUPPCState *env = &cpu->env;
678     hwaddr hash = 0; /* init to 0 to avoid used uninit warning */
679     bool key;
680     int type, ret;
681 
682     if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
683         return true;
684     }
685 
686     if (access_type == MMU_INST_FETCH) {
687         /* code access */
688         type = ACCESS_CODE;
689     } else if (guest_visible) {
690         /* data access */
691         type = env->access_type;
692     } else {
693         type = ACCESS_INT;
694     }
695 
696     ret = mmu6xx_get_physical_address(env, raddrp, protp, eaddr, &hash, &key,
697                                       access_type, type);
698     if (ret == 0) {
699         *psizep = TARGET_PAGE_BITS;
700         return true;
701     } else if (!guest_visible) {
702         return false;
703     }
704 
705     log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
706     if (type == ACCESS_CODE) {
707         switch (ret) {
708         case -1:
709             /* No matches in page tables or TLB */
710             cs->exception_index = POWERPC_EXCP_IFTLB;
711             env->error_code = 1 << 18;
712             env->spr[SPR_IMISS] = eaddr;
713             env->spr[SPR_ICMP] |= 0x80000000;
714             goto tlb_miss;
715         case -2:
716             /* Access rights violation */
717             cs->exception_index = POWERPC_EXCP_ISI;
718             env->error_code = 0x08000000;
719             break;
720         case -3:
721             /* No execute protection violation */
722             cs->exception_index = POWERPC_EXCP_ISI;
723             env->error_code = 0x10000000;
724             break;
725         case -4:
726             /* Direct store exception */
727             /* No code fetch is allowed in direct-store areas */
728             cs->exception_index = POWERPC_EXCP_ISI;
729             env->error_code = 0x10000000;
730             break;
731         }
732     } else {
733         switch (ret) {
734         case -1:
735             /* No matches in page tables or TLB */
736             if (access_type == MMU_DATA_STORE) {
737                 cs->exception_index = POWERPC_EXCP_DSTLB;
738                 env->error_code = 1 << 16;
739             } else {
740                 cs->exception_index = POWERPC_EXCP_DLTLB;
741                 env->error_code = 0;
742             }
743             env->spr[SPR_DMISS] = eaddr;
744             env->spr[SPR_DCMP] |= 0x80000000;
745 tlb_miss:
746             env->error_code |= key << 19;
747             env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
748                                   get_pteg_offset32(cpu, hash);
749             env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
750                                   get_pteg_offset32(cpu, ~hash);
751             break;
752         case -2:
753             /* Access rights violation */
754             cs->exception_index = POWERPC_EXCP_DSI;
755             env->error_code = 0;
756             env->spr[SPR_DAR] = eaddr;
757             if (access_type == MMU_DATA_STORE) {
758                 env->spr[SPR_DSISR] = 0x0A000000;
759             } else {
760                 env->spr[SPR_DSISR] = 0x08000000;
761             }
762             break;
763         case -4:
764             /* Direct store exception */
765             switch (type) {
766             case ACCESS_FLOAT:
767                 /* Floating point load/store */
768                 cs->exception_index = POWERPC_EXCP_ALIGN;
769                 env->error_code = POWERPC_EXCP_ALIGN_FP;
770                 env->spr[SPR_DAR] = eaddr;
771                 break;
772             case ACCESS_RES:
773                 /* lwarx, ldarx or stwcx. */
774                 cs->exception_index = POWERPC_EXCP_DSI;
775                 env->error_code = 0;
776                 env->spr[SPR_DAR] = eaddr;
777                 if (access_type == MMU_DATA_STORE) {
778                     env->spr[SPR_DSISR] = 0x06000000;
779                 } else {
780                     env->spr[SPR_DSISR] = 0x04000000;
781                 }
782                 break;
783             case ACCESS_EXT:
784                 /* eciwx or ecowx */
785                 cs->exception_index = POWERPC_EXCP_DSI;
786                 env->error_code = 0;
787                 env->spr[SPR_DAR] = eaddr;
788                 if (access_type == MMU_DATA_STORE) {
789                     env->spr[SPR_DSISR] = 0x06100000;
790                 } else {
791                     env->spr[SPR_DSISR] = 0x04100000;
792                 }
793                 break;
794             default:
795                 printf("DSI: invalid exception (%d)\n", ret);
796                 cs->exception_index = POWERPC_EXCP_PROGRAM;
797                 env->error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
798                 env->spr[SPR_DAR] = eaddr;
799                 break;
800             }
801             break;
802         }
803     }
804     return false;
805 }
806 
807 /*****************************************************************************/
808 
809 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
810                       hwaddr *raddrp, int *psizep, int *protp,
811                       int mmu_idx, bool guest_visible)
812 {
813     switch (cpu->env.mmu_model) {
814 #if defined(TARGET_PPC64)
815     case POWERPC_MMU_3_00:
816         if (ppc64_v3_radix(cpu)) {
817             return ppc_radix64_xlate(cpu, eaddr, access_type, raddrp,
818                                      psizep, protp, mmu_idx, guest_visible);
819         }
820         /* fall through */
821     case POWERPC_MMU_64B:
822     case POWERPC_MMU_2_03:
823     case POWERPC_MMU_2_06:
824     case POWERPC_MMU_2_07:
825         return ppc_hash64_xlate(cpu, eaddr, access_type,
826                                 raddrp, psizep, protp, mmu_idx, guest_visible);
827 #endif
828 
829     case POWERPC_MMU_32B:
830         return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp,
831                                psizep, protp, mmu_idx, guest_visible);
832     case POWERPC_MMU_BOOKE:
833     case POWERPC_MMU_BOOKE206:
834         return ppc_booke_xlate(cpu, eaddr, access_type, raddrp,
835                                psizep, protp, mmu_idx, guest_visible);
836     case POWERPC_MMU_SOFT_4xx:
837         return ppc_40x_xlate(cpu, eaddr, access_type, raddrp,
838                              psizep, protp, mmu_idx, guest_visible);
839     case POWERPC_MMU_SOFT_6xx:
840         return ppc_6xx_xlate(cpu, eaddr, access_type, raddrp,
841                              psizep, protp, mmu_idx, guest_visible);
842     case POWERPC_MMU_REAL:
843         return ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep,
844                                    protp);
845     case POWERPC_MMU_MPC8xx:
846         cpu_abort(env_cpu(&cpu->env), "MPC8xx MMU model is not implemented\n");
847     default:
848         cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n");
849     }
850 }
851 
852 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
853 {
854     PowerPCCPU *cpu = POWERPC_CPU(cs);
855     hwaddr raddr;
856     int s, p;
857 
858     /*
859      * Some MMUs have separate TLBs for code and data. If we only
860      * try an MMU_DATA_LOAD, we may not be able to read instructions
861      * mapped by code TLBs, so we also try a MMU_INST_FETCH.
862      */
863     if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p,
864                   ppc_env_mmu_index(&cpu->env, false), false) ||
865         ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p,
866                   ppc_env_mmu_index(&cpu->env, true), false)) {
867         return raddr & TARGET_PAGE_MASK;
868     }
869     return -1;
870 }
871