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