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