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