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