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