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