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