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