xref: /qemu/target/ppc/mmu_common.c (revision cd1038ec1d316aeca52a0c5d18da055d5aa014c9)
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 
37 /* #define DUMP_PAGE_TABLES */
38 
39 /* Context used internally during MMU translations */
40 typedef struct {
41     hwaddr raddr;      /* Real address             */
42     hwaddr eaddr;      /* Effective address        */
43     int prot;          /* Protection bits          */
44     hwaddr hash[2];    /* Pagetable hash values    */
45     target_ulong ptem; /* Virtual segment ID | API */
46     int key;           /* Access key               */
47     int nx;            /* Non-execute area         */
48 } mmu_ctx_t;
49 
50 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
51 {
52     PowerPCCPU *cpu = env_archcpu(env);
53     qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
54     assert(!cpu->env.has_hv_mode || !cpu->vhyp);
55 #if defined(TARGET_PPC64)
56     if (mmu_is_64bit(env->mmu_model)) {
57         target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
58         target_ulong htabsize = value & SDR_64_HTABSIZE;
59 
60         if (value & ~sdr_mask) {
61             qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx
62                      " set in SDR1", value & ~sdr_mask);
63             value &= sdr_mask;
64         }
65         if (htabsize > 28) {
66             qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx
67                      " stored in SDR1", htabsize);
68             return;
69         }
70     }
71 #endif /* defined(TARGET_PPC64) */
72     /* FIXME: Should check for valid HTABMASK values in 32-bit case */
73     env->spr[SPR_SDR1] = value;
74 }
75 
76 /*****************************************************************************/
77 /* PowerPC MMU emulation */
78 
79 static int pp_check(int key, int pp, int nx)
80 {
81     int access;
82 
83     /* Compute access rights */
84     access = 0;
85     if (key == 0) {
86         switch (pp) {
87         case 0x0:
88         case 0x1:
89         case 0x2:
90             access |= PAGE_WRITE;
91             /* fall through */
92         case 0x3:
93             access |= PAGE_READ;
94             break;
95         }
96     } else {
97         switch (pp) {
98         case 0x0:
99             access = 0;
100             break;
101         case 0x1:
102         case 0x3:
103             access = PAGE_READ;
104             break;
105         case 0x2:
106             access = PAGE_READ | PAGE_WRITE;
107             break;
108         }
109     }
110     if (nx == 0) {
111         access |= PAGE_EXEC;
112     }
113 
114     return access;
115 }
116 
117 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
118                                     int way, int is_code)
119 {
120     int nr;
121 
122     /* Select TLB num in a way from address */
123     nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
124     /* Select TLB way */
125     nr += env->tlb_per_way * way;
126     /* 6xx has separate TLBs for instructions and data */
127     if (is_code) {
128         nr += env->nb_tlb;
129     }
130 
131     return nr;
132 }
133 
134 static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
135                                 target_ulong pte1, int h,
136                                 MMUAccessType access_type)
137 {
138     target_ulong ptem, mmask;
139     int access, ret, pteh, ptev, pp;
140 
141     ret = -1;
142     /* Check validity and table match */
143     ptev = pte_is_valid(pte0);
144     pteh = (pte0 >> 6) & 1;
145     if (ptev && h == pteh) {
146         /* Check vsid & api */
147         ptem = pte0 & PTE_PTEM_MASK;
148         mmask = PTE_CHECK_MASK;
149         pp = pte1 & 0x00000003;
150         if (ptem == ctx->ptem) {
151             if (ctx->raddr != (hwaddr)-1ULL) {
152                 /* all matches should have equal RPN, WIMG & PP */
153                 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
154                     qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
155                     return -3;
156                 }
157             }
158             /* Compute access rights */
159             access = pp_check(ctx->key, pp, ctx->nx);
160             /* Keep the matching PTE information */
161             ctx->raddr = pte1;
162             ctx->prot = access;
163             if (check_prot_access_type(ctx->prot, access_type)) {
164                 /* Access granted */
165                 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
166                 ret = 0;
167             } else {
168                 /* Access right violation */
169                 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
170                 ret = -2;
171             }
172         }
173     }
174 
175     return ret;
176 }
177 
178 static int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
179                             int ret, MMUAccessType access_type)
180 {
181     int store = 0;
182 
183     /* Update page flags */
184     if (!(*pte1p & 0x00000100)) {
185         /* Update accessed flag */
186         *pte1p |= 0x00000100;
187         store = 1;
188     }
189     if (!(*pte1p & 0x00000080)) {
190         if (access_type == MMU_DATA_STORE && ret == 0) {
191             /* Update changed flag */
192             *pte1p |= 0x00000080;
193             store = 1;
194         } else {
195             /* Force page fault for first write access */
196             ctx->prot &= ~PAGE_WRITE;
197         }
198     }
199 
200     return store;
201 }
202 
203 /* Software driven TLB helpers */
204 
205 static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
206                             target_ulong eaddr, MMUAccessType access_type)
207 {
208     ppc6xx_tlb_t *tlb;
209     int nr, best, way;
210     int ret;
211 
212     best = -1;
213     ret = -1; /* No TLB found */
214     for (way = 0; way < env->nb_ways; way++) {
215         nr = ppc6xx_tlb_getnum(env, eaddr, way, access_type == MMU_INST_FETCH);
216         tlb = &env->tlb.tlb6[nr];
217         /* This test "emulates" the PTE index match for hardware TLBs */
218         if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
219             qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx
220                           " " TARGET_FMT_lx "] <> " TARGET_FMT_lx "\n",
221                           nr, env->nb_tlb,
222                           pte_is_valid(tlb->pte0) ? "valid" : "inval",
223                           tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
224             continue;
225         }
226         qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s " TARGET_FMT_lx " <> "
227                       TARGET_FMT_lx " " TARGET_FMT_lx " %c %c\n",
228                       nr, env->nb_tlb,
229                       pte_is_valid(tlb->pte0) ? "valid" : "inval",
230                       tlb->EPN, eaddr, tlb->pte1,
231                       access_type == MMU_DATA_STORE ? 'S' : 'L',
232                       access_type == MMU_INST_FETCH ? 'I' : 'D');
233         switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1,
234                                      0, access_type)) {
235         case -2:
236             /* Access violation */
237             ret = -2;
238             best = nr;
239             break;
240         case -1: /* No match */
241         case -3: /* TLB inconsistency */
242         default:
243             break;
244         case 0:
245             /* access granted */
246             /*
247              * XXX: we should go on looping to check all TLBs
248              *      consistency but we can speed-up the whole thing as
249              *      the result would be undefined if TLBs are not
250              *      consistent.
251              */
252             ret = 0;
253             best = nr;
254             goto done;
255         }
256     }
257     if (best != -1) {
258 done:
259         qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx
260                       " prot=%01x ret=%d\n",
261                       ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
262         /* Update page flags */
263         pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, access_type);
264     }
265 #if defined(DUMP_PAGE_TABLES)
266     if (qemu_loglevel_mask(CPU_LOG_MMU)) {
267         CPUState *cs = env_cpu(env);
268         hwaddr base = ppc_hash32_hpt_base(env_archcpu(env));
269         hwaddr len = ppc_hash32_hpt_mask(env_archcpu(env)) + 0x80;
270         uint32_t a0, a1, a2, a3;
271 
272         qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n",
273                  base, len);
274         for (hwaddr curaddr = base; curaddr < base + len; curaddr += 16) {
275             a0 = ldl_phys(cs->as, curaddr);
276             a1 = ldl_phys(cs->as, curaddr + 4);
277             a2 = ldl_phys(cs->as, curaddr + 8);
278             a3 = ldl_phys(cs->as, curaddr + 12);
279             if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
280                 qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
281                          curaddr, a0, a1, a2, a3);
282             }
283         }
284     }
285 #endif
286     return ret;
287 }
288 
289 /* Perform BAT hit & translation */
290 static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
291                                  int *validp, int *protp, target_ulong *BATu,
292                                  target_ulong *BATl)
293 {
294     target_ulong bl;
295     int pp, valid, prot;
296 
297     bl = (*BATu & 0x00001FFC) << 15;
298     valid = 0;
299     prot = 0;
300     if ((!FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000002)) ||
301         (FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000001))) {
302         valid = 1;
303         pp = *BATl & 0x00000003;
304         if (pp != 0) {
305             prot = PAGE_READ | PAGE_EXEC;
306             if (pp == 0x2) {
307                 prot |= PAGE_WRITE;
308             }
309         }
310     }
311     *blp = bl;
312     *validp = valid;
313     *protp = prot;
314 }
315 
316 static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
317                            target_ulong virtual, MMUAccessType access_type)
318 {
319     target_ulong *BATlt, *BATut, *BATu, *BATl;
320     target_ulong BEPIl, BEPIu, bl;
321     int i, valid, prot;
322     int ret = -1;
323     bool ifetch = access_type == MMU_INST_FETCH;
324 
325     qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
326                   ifetch ? 'I' : 'D', virtual);
327     if (ifetch) {
328         BATlt = env->IBAT[1];
329         BATut = env->IBAT[0];
330     } else {
331         BATlt = env->DBAT[1];
332         BATut = env->DBAT[0];
333     }
334     for (i = 0; i < env->nb_BATs; i++) {
335         BATu = &BATut[i];
336         BATl = &BATlt[i];
337         BEPIu = *BATu & 0xF0000000;
338         BEPIl = *BATu & 0x0FFE0000;
339         bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
340         qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
341                       TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
342                       ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
343         if ((virtual & 0xF0000000) == BEPIu &&
344             ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
345             /* BAT matches */
346             if (valid != 0) {
347                 /* Get physical address */
348                 ctx->raddr = (*BATl & 0xF0000000) |
349                     ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
350                     (virtual & 0x0001F000);
351                 /* Compute access rights */
352                 ctx->prot = prot;
353                 if (check_prot_access_type(ctx->prot, access_type)) {
354                     qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " HWADDR_FMT_plx
355                                   " prot=%c%c\n", i, ctx->raddr,
356                                   ctx->prot & PAGE_READ ? 'R' : '-',
357                                   ctx->prot & PAGE_WRITE ? 'W' : '-');
358                     ret = 0;
359                 } else {
360                     ret = -2;
361                 }
362                 break;
363             }
364         }
365     }
366     if (ret < 0) {
367         if (qemu_log_enabled()) {
368             qemu_log_mask(CPU_LOG_MMU, "no BAT match for "
369                           TARGET_FMT_lx ":\n", virtual);
370             for (i = 0; i < 4; i++) {
371                 BATu = &BATut[i];
372                 BATl = &BATlt[i];
373                 BEPIu = *BATu & 0xF0000000;
374                 BEPIl = *BATu & 0x0FFE0000;
375                 bl = (*BATu & 0x00001FFC) << 15;
376                 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx
377                               " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx
378                               "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " "
379                               TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D',
380                               i, virtual, *BATu, *BATl, BEPIu, BEPIl, bl);
381             }
382         }
383     }
384     /* No hit */
385     return ret;
386 }
387 
388 static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
389                                        target_ulong eaddr,
390                                        MMUAccessType access_type, int type)
391 {
392     PowerPCCPU *cpu = env_archcpu(env);
393     hwaddr hash;
394     target_ulong vsid, sr, pgidx;
395     int ds, target_page_bits;
396     bool pr;
397 
398     /* First try to find a BAT entry if there are any */
399     if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) {
400         return 0;
401     }
402 
403     /* Perform segment based translation when no BATs matched */
404     pr = FIELD_EX64(env->msr, MSR, PR);
405     ctx->eaddr = eaddr;
406 
407     sr = env->sr[eaddr >> 28];
408     ctx->key = (((sr & 0x20000000) && pr) ||
409                 ((sr & 0x40000000) && !pr)) ? 1 : 0;
410     ds = sr & 0x80000000 ? 1 : 0;
411     ctx->nx = sr & 0x10000000 ? 1 : 0;
412     vsid = sr & 0x00FFFFFF;
413     target_page_bits = TARGET_PAGE_BITS;
414     qemu_log_mask(CPU_LOG_MMU,
415                   "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
416                   " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
417                   " ir=%d dr=%d pr=%d %d t=%d\n",
418                   eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr,
419                   (int)FIELD_EX64(env->msr, MSR, IR),
420                   (int)FIELD_EX64(env->msr, MSR, DR), pr ? 1 : 0,
421                   access_type == MMU_DATA_STORE, type);
422     pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
423     hash = vsid ^ pgidx;
424     ctx->ptem = (vsid << 7) | (pgidx >> 10);
425 
426     qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid "
427                   TARGET_FMT_lx "\n", ctx->key, ds, ctx->nx, vsid);
428     if (!ds) {
429         /* Check if instruction fetch is allowed, if needed */
430         if (type == ACCESS_CODE && ctx->nx) {
431             qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
432             return -3;
433         }
434         /* Page address translation */
435         qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
436                       HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
437                       ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
438         ctx->hash[0] = hash;
439         ctx->hash[1] = ~hash;
440 
441         /* Initialize real address with an invalid value */
442         ctx->raddr = (hwaddr)-1ULL;
443         /* Software TLB search */
444         return ppc6xx_tlb_check(env, ctx, eaddr, access_type);
445     }
446 
447     /* Direct-store segment : absolutely *BUGGY* for now */
448     qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
449     switch (type) {
450     case ACCESS_INT:
451         /* Integer load/store : only access allowed */
452         break;
453     case ACCESS_CODE:
454         /* No code fetch is allowed in direct-store areas */
455         return -4;
456     case ACCESS_FLOAT:
457         /* Floating point load/store */
458         return -4;
459     case ACCESS_RES:
460         /* lwarx, ldarx or srwcx. */
461         return -4;
462     case ACCESS_CACHE:
463         /*
464          * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
465          *
466          * Should make the instruction do no-op.  As it already do
467          * no-op, it's quite easy :-)
468          */
469         ctx->raddr = eaddr;
470         return 0;
471     case ACCESS_EXT:
472         /* eciwx or ecowx */
473         return -4;
474     default:
475         qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need address"
476                                    " translation\n");
477         return -4;
478     }
479     if ((access_type == MMU_DATA_STORE || ctx->key != 1) &&
480         (access_type == MMU_DATA_LOAD || ctx->key != 0)) {
481         ctx->raddr = eaddr;
482         return 2;
483     }
484     return -2;
485 }
486 
487 /* Generic TLB check function for embedded PowerPC implementations */
488 static bool ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
489                              hwaddr *raddrp,
490                              target_ulong address, uint32_t pid, int i)
491 {
492     target_ulong mask;
493 
494     /* Check valid flag */
495     if (!(tlb->prot & PAGE_VALID)) {
496         return false;
497     }
498     mask = ~(tlb->size - 1);
499     qemu_log_mask(CPU_LOG_MMU, "%s: TLB %d address " TARGET_FMT_lx
500                   " PID %u <=> " TARGET_FMT_lx " " TARGET_FMT_lx " %u %x\n",
501                   __func__, i, address, pid, tlb->EPN,
502                   mask, (uint32_t)tlb->PID, tlb->prot);
503     /* Check PID */
504     if (tlb->PID != 0 && tlb->PID != pid) {
505         return false;
506     }
507     /* Check effective address */
508     if ((address & mask) != tlb->EPN) {
509         return false;
510     }
511     *raddrp = (tlb->RPN & mask) | (address & ~mask);
512     return true;
513 }
514 
515 /* Generic TLB search function for PowerPC embedded implementations */
516 int ppcemb_tlb_search(CPUPPCState *env, target_ulong address, uint32_t pid)
517 {
518     ppcemb_tlb_t *tlb;
519     hwaddr raddr;
520     int i;
521 
522     for (i = 0; i < env->nb_tlb; i++) {
523         tlb = &env->tlb.tlbe[i];
524         if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, i)) {
525             return i;
526         }
527     }
528     return -1;
529 }
530 
531 static int mmu40x_get_physical_address(CPUPPCState *env, hwaddr *raddr,
532                                        int *prot, target_ulong address,
533                                        MMUAccessType access_type)
534 {
535     ppcemb_tlb_t *tlb;
536     int i, ret, zsel, zpr, pr;
537 
538     ret = -1;
539     pr = FIELD_EX64(env->msr, MSR, PR);
540     for (i = 0; i < env->nb_tlb; i++) {
541         tlb = &env->tlb.tlbe[i];
542         if (!ppcemb_tlb_check(env, tlb, raddr, address,
543                               env->spr[SPR_40x_PID], i)) {
544             continue;
545         }
546         zsel = (tlb->attr >> 4) & 0xF;
547         zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
548         qemu_log_mask(CPU_LOG_MMU,
549                       "%s: TLB %d zsel %d zpr %d ty %d attr %08x\n",
550                       __func__, i, zsel, zpr, access_type, tlb->attr);
551         /* Check execute enable bit */
552         switch (zpr) {
553         case 0x2:
554             if (pr != 0) {
555                 goto check_perms;
556             }
557             /* fall through */
558         case 0x3:
559             /* All accesses granted */
560             *prot = PAGE_RWX;
561             ret = 0;
562             break;
563 
564         case 0x0:
565             if (pr != 0) {
566                 /* Raise Zone protection fault.  */
567                 env->spr[SPR_40x_ESR] = 1 << 22;
568                 *prot = 0;
569                 ret = -2;
570                 break;
571             }
572             /* fall through */
573         case 0x1:
574 check_perms:
575             /* Check from TLB entry */
576             *prot = tlb->prot;
577             if (check_prot_access_type(*prot, access_type)) {
578                 ret = 0;
579             } else {
580                 env->spr[SPR_40x_ESR] = 0;
581                 ret = -2;
582             }
583             break;
584         }
585     }
586     qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
587                   HWADDR_FMT_plx " %d %d\n",  __func__,
588                   ret < 0 ? "refused" : "granted", address,
589                   ret < 0 ? 0 : *raddr, *prot, ret);
590 
591     return ret;
592 }
593 
594 static bool mmubooke_check_pid(CPUPPCState *env, ppcemb_tlb_t *tlb,
595                                hwaddr *raddr, target_ulong addr, int i)
596 {
597     if (ppcemb_tlb_check(env, tlb, raddr, addr, env->spr[SPR_BOOKE_PID], i)) {
598         if (!env->nb_pids) {
599             /* Extend the physical address to 36 bits */
600             *raddr |= (uint64_t)(tlb->RPN & 0xF) << 32;
601         }
602         return true;
603     } else if (!env->nb_pids) {
604         return false;
605     }
606     if (env->spr[SPR_BOOKE_PID1] &&
607         ppcemb_tlb_check(env, tlb, raddr, addr, env->spr[SPR_BOOKE_PID1], i)) {
608         return true;
609     }
610     if (env->spr[SPR_BOOKE_PID2] &&
611         ppcemb_tlb_check(env, tlb, raddr, addr, env->spr[SPR_BOOKE_PID2], i)) {
612         return true;
613     }
614     return false;
615 }
616 
617 static int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb,
618                               hwaddr *raddr, int *prot, target_ulong address,
619                               MMUAccessType access_type, int i)
620 {
621     if (!mmubooke_check_pid(env, tlb, raddr, address, i)) {
622         qemu_log_mask(CPU_LOG_MMU, "%s: TLB entry not found\n", __func__);
623         return -1;
624     }
625 
626     /* Check the address space */
627     if ((access_type == MMU_INST_FETCH ?
628         FIELD_EX64(env->msr, MSR, IR) :
629         FIELD_EX64(env->msr, MSR, DR)) != (tlb->attr & 1)) {
630         qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__);
631         return -1;
632     }
633 
634     if (FIELD_EX64(env->msr, MSR, PR)) {
635         *prot = tlb->prot & 0xF;
636     } else {
637         *prot = (tlb->prot >> 4) & 0xF;
638     }
639     if (check_prot_access_type(*prot, access_type)) {
640         qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
641         return 0;
642     }
643 
644     qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, *prot);
645     return access_type == MMU_INST_FETCH ? -3 : -2;
646 }
647 
648 static int mmubooke_get_physical_address(CPUPPCState *env, hwaddr *raddr,
649                                          int *prot, target_ulong address,
650                                          MMUAccessType access_type)
651 {
652     ppcemb_tlb_t *tlb;
653     int i, ret = -1;
654 
655     for (i = 0; i < env->nb_tlb; i++) {
656         tlb = &env->tlb.tlbe[i];
657         ret = mmubooke_check_tlb(env, tlb, raddr, prot, address,
658                                  access_type, i);
659         if (ret != -1) {
660             break;
661         }
662     }
663     qemu_log_mask(CPU_LOG_MMU,
664                   "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
665                   " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
666                   address, ret < 0 ? -1 : *raddr, ret == -1 ? 0 : *prot, ret);
667     return ret;
668 }
669 
670 hwaddr booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb)
671 {
672     int tlbm_size;
673 
674     tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
675 
676     return 1024ULL << tlbm_size;
677 }
678 
679 /* TLB check function for MAS based SoftTLBs */
680 int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, hwaddr *raddrp,
681                      target_ulong address, uint32_t pid)
682 {
683     hwaddr mask;
684     uint32_t tlb_pid;
685 
686     if (!FIELD_EX64(env->msr, MSR, CM)) {
687         /* In 32bit mode we can only address 32bit EAs */
688         address = (uint32_t)address;
689     }
690 
691     /* Check valid flag */
692     if (!(tlb->mas1 & MAS1_VALID)) {
693         return -1;
694     }
695 
696     mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
697     qemu_log_mask(CPU_LOG_MMU, "%s: TLB ADDR=0x" TARGET_FMT_lx
698                   " PID=0x%x MAS1=0x%x MAS2=0x%" PRIx64 " mask=0x%"
699                   HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" PRIx32 "\n",
700                   __func__, address, pid, tlb->mas1, tlb->mas2, mask,
701                   tlb->mas7_3, tlb->mas8);
702 
703     /* Check PID */
704     tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
705     if (tlb_pid != 0 && tlb_pid != pid) {
706         return -1;
707     }
708 
709     /* Check effective address */
710     if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
711         return -1;
712     }
713 
714     if (raddrp) {
715         *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
716     }
717 
718     return 0;
719 }
720 
721 static bool is_epid_mmu(int mmu_idx)
722 {
723     return mmu_idx == PPC_TLB_EPID_STORE || mmu_idx == PPC_TLB_EPID_LOAD;
724 }
725 
726 static uint32_t mmubooke206_esr(int mmu_idx, MMUAccessType access_type)
727 {
728     uint32_t esr = 0;
729     if (access_type == MMU_DATA_STORE) {
730         esr |= ESR_ST;
731     }
732     if (is_epid_mmu(mmu_idx)) {
733         esr |= ESR_EPID;
734     }
735     return esr;
736 }
737 
738 /*
739  * Get EPID register given the mmu_idx. If this is regular load,
740  * construct the EPID access bits from current processor state
741  *
742  * Get the effective AS and PR bits and the PID. The PID is returned
743  * only if EPID load is requested, otherwise the caller must detect
744  * the correct EPID.  Return true if valid EPID is returned.
745  */
746 static bool mmubooke206_get_as(CPUPPCState *env,
747                                int mmu_idx, uint32_t *epid_out,
748                                bool *as_out, bool *pr_out)
749 {
750     if (is_epid_mmu(mmu_idx)) {
751         uint32_t epidr;
752         if (mmu_idx == PPC_TLB_EPID_STORE) {
753             epidr = env->spr[SPR_BOOKE_EPSC];
754         } else {
755             epidr = env->spr[SPR_BOOKE_EPLC];
756         }
757         *epid_out = (epidr & EPID_EPID) >> EPID_EPID_SHIFT;
758         *as_out = !!(epidr & EPID_EAS);
759         *pr_out = !!(epidr & EPID_EPR);
760         return true;
761     } else {
762         *as_out = FIELD_EX64(env->msr, MSR, DS);
763         *pr_out = FIELD_EX64(env->msr, MSR, PR);
764         return false;
765     }
766 }
767 
768 /* Check if the tlb found by hashing really matches */
769 static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
770                                  hwaddr *raddr, int *prot,
771                                  target_ulong address,
772                                  MMUAccessType access_type, int mmu_idx)
773 {
774     uint32_t epid;
775     bool as, pr;
776     bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
777 
778     if (!use_epid) {
779         if (ppcmas_tlb_check(env, tlb, raddr, address,
780                              env->spr[SPR_BOOKE_PID]) >= 0) {
781             goto found_tlb;
782         }
783 
784         if (env->spr[SPR_BOOKE_PID1] &&
785             ppcmas_tlb_check(env, tlb, raddr, address,
786                              env->spr[SPR_BOOKE_PID1]) >= 0) {
787             goto found_tlb;
788         }
789 
790         if (env->spr[SPR_BOOKE_PID2] &&
791             ppcmas_tlb_check(env, tlb, raddr, address,
792                              env->spr[SPR_BOOKE_PID2]) >= 0) {
793             goto found_tlb;
794         }
795     } else {
796         if (ppcmas_tlb_check(env, tlb, raddr, address, epid) >= 0) {
797             goto found_tlb;
798         }
799     }
800 
801     qemu_log_mask(CPU_LOG_MMU, "%s: No TLB entry found for effective address "
802                   "0x" TARGET_FMT_lx "\n", __func__, address);
803     return -1;
804 
805 found_tlb:
806 
807     /* Check the address space and permissions */
808     if (access_type == MMU_INST_FETCH) {
809         /* There is no way to fetch code using epid load */
810         assert(!use_epid);
811         as = FIELD_EX64(env->msr, MSR, IR);
812     }
813 
814     if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
815         qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__);
816         return -1;
817     }
818 
819     *prot = 0;
820     if (pr) {
821         if (tlb->mas7_3 & MAS3_UR) {
822             *prot |= PAGE_READ;
823         }
824         if (tlb->mas7_3 & MAS3_UW) {
825             *prot |= PAGE_WRITE;
826         }
827         if (tlb->mas7_3 & MAS3_UX) {
828             *prot |= PAGE_EXEC;
829         }
830     } else {
831         if (tlb->mas7_3 & MAS3_SR) {
832             *prot |= PAGE_READ;
833         }
834         if (tlb->mas7_3 & MAS3_SW) {
835             *prot |= PAGE_WRITE;
836         }
837         if (tlb->mas7_3 & MAS3_SX) {
838             *prot |= PAGE_EXEC;
839         }
840     }
841     if (check_prot_access_type(*prot, access_type)) {
842         qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
843         return 0;
844     }
845 
846     qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, *prot);
847     return access_type == MMU_INST_FETCH ? -3 : -2;
848 }
849 
850 static int mmubooke206_get_physical_address(CPUPPCState *env, hwaddr *raddr,
851                                             int *prot, target_ulong address,
852                                             MMUAccessType access_type,
853                                             int mmu_idx)
854 {
855     ppcmas_tlb_t *tlb;
856     int i, j, ret = -1;
857 
858     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
859         int ways = booke206_tlb_ways(env, i);
860         for (j = 0; j < ways; j++) {
861             tlb = booke206_get_tlbm(env, i, address, j);
862             if (!tlb) {
863                 continue;
864             }
865             ret = mmubooke206_check_tlb(env, tlb, raddr, prot, address,
866                                         access_type, mmu_idx);
867             if (ret != -1) {
868                 goto found_tlb;
869             }
870         }
871     }
872 
873 found_tlb:
874 
875     qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
876                   HWADDR_FMT_plx " %d %d\n", __func__,
877                   ret < 0 ? "refused" : "granted", address,
878                   ret < 0 ? -1 : *raddr, ret == -1 ? 0 : *prot, ret);
879     return ret;
880 }
881 
882 static const char *book3e_tsize_to_str[32] = {
883     "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
884     "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
885     "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
886     "1T", "2T"
887 };
888 
889 static void mmubooke_dump_mmu(CPUPPCState *env)
890 {
891     ppcemb_tlb_t *entry;
892     int i;
893 
894 #ifdef CONFIG_KVM
895     if (kvm_enabled() && !env->kvm_sw_tlb) {
896         qemu_printf("Cannot access KVM TLB\n");
897         return;
898     }
899 #endif
900 
901     qemu_printf("\nTLB:\n");
902     qemu_printf("Effective          Physical           Size PID   Prot     "
903                 "Attr\n");
904 
905     entry = &env->tlb.tlbe[0];
906     for (i = 0; i < env->nb_tlb; i++, entry++) {
907         hwaddr ea, pa;
908         target_ulong mask;
909         uint64_t size = (uint64_t)entry->size;
910         char size_buf[20];
911 
912         /* Check valid flag */
913         if (!(entry->prot & PAGE_VALID)) {
914             continue;
915         }
916 
917         mask = ~(entry->size - 1);
918         ea = entry->EPN & mask;
919         pa = entry->RPN & mask;
920         /* Extend the physical address to 36 bits */
921         pa |= (hwaddr)(entry->RPN & 0xF) << 32;
922         if (size >= 1 * MiB) {
923             snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB);
924         } else {
925             snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB);
926         }
927         qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
928                     (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
929                     entry->prot, entry->attr);
930     }
931 
932 }
933 
934 static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset,
935                                      int tlbsize)
936 {
937     ppcmas_tlb_t *entry;
938     int i;
939 
940     qemu_printf("\nTLB%d:\n", tlbn);
941     qemu_printf("Effective          Physical           Size TID   TS SRWX"
942                 " URWX WIMGE U0123\n");
943 
944     entry = &env->tlb.tlbm[offset];
945     for (i = 0; i < tlbsize; i++, entry++) {
946         hwaddr ea, pa, size;
947         int tsize;
948 
949         if (!(entry->mas1 & MAS1_VALID)) {
950             continue;
951         }
952 
953         tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
954         size = 1024ULL << tsize;
955         ea = entry->mas2 & ~(size - 1);
956         pa = entry->mas7_3 & ~(size - 1);
957 
958         qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u  S%c%c%c"
959                     " U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
960                     (uint64_t)ea, (uint64_t)pa,
961                     book3e_tsize_to_str[tsize],
962                     (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
963                     (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
964                     entry->mas7_3 & MAS3_SR ? 'R' : '-',
965                     entry->mas7_3 & MAS3_SW ? 'W' : '-',
966                     entry->mas7_3 & MAS3_SX ? 'X' : '-',
967                     entry->mas7_3 & MAS3_UR ? 'R' : '-',
968                     entry->mas7_3 & MAS3_UW ? 'W' : '-',
969                     entry->mas7_3 & MAS3_UX ? 'X' : '-',
970                     entry->mas2 & MAS2_W ? 'W' : '-',
971                     entry->mas2 & MAS2_I ? 'I' : '-',
972                     entry->mas2 & MAS2_M ? 'M' : '-',
973                     entry->mas2 & MAS2_G ? 'G' : '-',
974                     entry->mas2 & MAS2_E ? 'E' : '-',
975                     entry->mas7_3 & MAS3_U0 ? '0' : '-',
976                     entry->mas7_3 & MAS3_U1 ? '1' : '-',
977                     entry->mas7_3 & MAS3_U2 ? '2' : '-',
978                     entry->mas7_3 & MAS3_U3 ? '3' : '-');
979     }
980 }
981 
982 static void mmubooke206_dump_mmu(CPUPPCState *env)
983 {
984     int offset = 0;
985     int i;
986 
987 #ifdef CONFIG_KVM
988     if (kvm_enabled() && !env->kvm_sw_tlb) {
989         qemu_printf("Cannot access KVM TLB\n");
990         return;
991     }
992 #endif
993 
994     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
995         int size = booke206_tlb_size(env, i);
996 
997         if (size == 0) {
998             continue;
999         }
1000 
1001         mmubooke206_dump_one_tlb(env, i, offset, size);
1002         offset += size;
1003     }
1004 }
1005 
1006 static void mmu6xx_dump_BATs(CPUPPCState *env, int type)
1007 {
1008     target_ulong *BATlt, *BATut, *BATu, *BATl;
1009     target_ulong BEPIl, BEPIu, bl;
1010     int i;
1011 
1012     switch (type) {
1013     case ACCESS_CODE:
1014         BATlt = env->IBAT[1];
1015         BATut = env->IBAT[0];
1016         break;
1017     default:
1018         BATlt = env->DBAT[1];
1019         BATut = env->DBAT[0];
1020         break;
1021     }
1022 
1023     for (i = 0; i < env->nb_BATs; i++) {
1024         BATu = &BATut[i];
1025         BATl = &BATlt[i];
1026         BEPIu = *BATu & 0xF0000000;
1027         BEPIl = *BATu & 0x0FFE0000;
1028         bl = (*BATu & 0x00001FFC) << 15;
1029         qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
1030                     " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
1031                     TARGET_FMT_lx " " TARGET_FMT_lx "\n",
1032                     type == ACCESS_CODE ? "code" : "data", i,
1033                     *BATu, *BATl, BEPIu, BEPIl, bl);
1034     }
1035 }
1036 
1037 static void mmu6xx_dump_mmu(CPUPPCState *env)
1038 {
1039     PowerPCCPU *cpu = env_archcpu(env);
1040     ppc6xx_tlb_t *tlb;
1041     target_ulong sr;
1042     int type, way, entry, i;
1043 
1044     qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu));
1045     qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu));
1046 
1047     qemu_printf("\nSegment registers:\n");
1048     for (i = 0; i < 32; i++) {
1049         sr = env->sr[i];
1050         if (sr & 0x80000000) {
1051             qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1052                         "CNTLR_SPEC=0x%05x\n", i,
1053                         sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
1054                         sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF),
1055                         (uint32_t)(sr & 0xFFFFF));
1056         } else {
1057             qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i,
1058                         sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
1059                         sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0,
1060                         (uint32_t)(sr & 0x00FFFFFF));
1061         }
1062     }
1063 
1064     qemu_printf("\nBATs:\n");
1065     mmu6xx_dump_BATs(env, ACCESS_INT);
1066     mmu6xx_dump_BATs(env, ACCESS_CODE);
1067 
1068     qemu_printf("\nTLBs                       [EPN    EPN + SIZE]\n");
1069     for (type = 0; type < 2; type++) {
1070         for (way = 0; way < env->nb_ways; way++) {
1071             for (entry = env->nb_tlb * type + env->tlb_per_way * way;
1072                  entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1));
1073                  entry++) {
1074 
1075                 tlb = &env->tlb.tlb6[entry];
1076                 qemu_printf("%s TLB %02d/%02d way:%d %s ["
1077                             TARGET_FMT_lx " " TARGET_FMT_lx "]\n",
1078                             type ? "code" : "data", entry % env->nb_tlb,
1079                             env->nb_tlb, way,
1080                             pte_is_valid(tlb->pte0) ? "valid" : "inval",
1081                             tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE);
1082             }
1083         }
1084     }
1085 }
1086 
1087 void dump_mmu(CPUPPCState *env)
1088 {
1089     switch (env->mmu_model) {
1090     case POWERPC_MMU_BOOKE:
1091         mmubooke_dump_mmu(env);
1092         break;
1093     case POWERPC_MMU_BOOKE206:
1094         mmubooke206_dump_mmu(env);
1095         break;
1096     case POWERPC_MMU_SOFT_6xx:
1097         mmu6xx_dump_mmu(env);
1098         break;
1099 #if defined(TARGET_PPC64)
1100     case POWERPC_MMU_64B:
1101     case POWERPC_MMU_2_03:
1102     case POWERPC_MMU_2_06:
1103     case POWERPC_MMU_2_07:
1104         dump_slb(env_archcpu(env));
1105         break;
1106     case POWERPC_MMU_3_00:
1107         if (ppc64_v3_radix(env_archcpu(env))) {
1108             qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n",
1109                           __func__);
1110         } else {
1111             dump_slb(env_archcpu(env));
1112         }
1113         break;
1114 #endif
1115     default:
1116         qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
1117     }
1118 }
1119 
1120 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
1121                                          MMUAccessType access_type, int mmu_idx)
1122 {
1123     uint32_t epid;
1124     bool as, pr;
1125     uint32_t missed_tid = 0;
1126     bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
1127 
1128     if (access_type == MMU_INST_FETCH) {
1129         as = FIELD_EX64(env->msr, MSR, IR);
1130     }
1131     env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1132     env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1133     env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1134     env->spr[SPR_BOOKE_MAS3] = 0;
1135     env->spr[SPR_BOOKE_MAS6] = 0;
1136     env->spr[SPR_BOOKE_MAS7] = 0;
1137 
1138     /* AS */
1139     if (as) {
1140         env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1141         env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1142     }
1143 
1144     env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1145     env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1146 
1147     if (!use_epid) {
1148         switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1149         case MAS4_TIDSELD_PID0:
1150             missed_tid = env->spr[SPR_BOOKE_PID];
1151             break;
1152         case MAS4_TIDSELD_PID1:
1153             missed_tid = env->spr[SPR_BOOKE_PID1];
1154             break;
1155         case MAS4_TIDSELD_PID2:
1156             missed_tid = env->spr[SPR_BOOKE_PID2];
1157             break;
1158         }
1159         env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1160     } else {
1161         missed_tid = epid;
1162         env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
1163     }
1164     env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
1165 
1166 
1167     /* next victim logic */
1168     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1169     env->last_way++;
1170     env->last_way &= booke206_tlb_ways(env, 0) - 1;
1171     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1172 }
1173 
1174 static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr eaddr,
1175                             MMUAccessType access_type,
1176                             hwaddr *raddrp, int *psizep, int *protp,
1177                             int mmu_idx, bool guest_visible)
1178 {
1179     CPUState *cs = CPU(cpu);
1180     CPUPPCState *env = &cpu->env;
1181     hwaddr raddr;
1182     int prot, ret;
1183 
1184     if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1185         ret = mmubooke206_get_physical_address(env, &raddr, &prot, eaddr,
1186                                                access_type, mmu_idx);
1187     } else {
1188         ret = mmubooke_get_physical_address(env, &raddr, &prot, eaddr,
1189                                             access_type);
1190     }
1191     if (ret == 0) {
1192         *raddrp = raddr;
1193         *protp = prot;
1194         *psizep = TARGET_PAGE_BITS;
1195         return true;
1196     } else if (!guest_visible) {
1197         return false;
1198     }
1199 
1200     log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
1201     env->error_code = 0;
1202     switch (ret) {
1203     case -1:
1204         /* No matches in page tables or TLB */
1205         if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1206             booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
1207         }
1208         cs->exception_index = (access_type == MMU_INST_FETCH) ?
1209                               POWERPC_EXCP_ITLB : POWERPC_EXCP_DTLB;
1210         env->spr[SPR_BOOKE_DEAR] = eaddr;
1211         env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
1212         break;
1213     case -2:
1214         /* Access rights violation */
1215         cs->exception_index = (access_type == MMU_INST_FETCH) ?
1216                               POWERPC_EXCP_ISI : POWERPC_EXCP_DSI;
1217         if (access_type != MMU_INST_FETCH) {
1218             env->spr[SPR_BOOKE_DEAR] = eaddr;
1219             env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
1220         }
1221         break;
1222     case -3:
1223         /* No execute protection violation */
1224         cs->exception_index = POWERPC_EXCP_ISI;
1225         env->spr[SPR_BOOKE_ESR] = 0;
1226         break;
1227     }
1228 
1229     return false;
1230 }
1231 
1232 static bool ppc_real_mode_xlate(PowerPCCPU *cpu, vaddr eaddr,
1233                                 MMUAccessType access_type,
1234                                 hwaddr *raddrp, int *psizep, int *protp)
1235 {
1236     CPUPPCState *env = &cpu->env;
1237 
1238     if (access_type == MMU_INST_FETCH ? !FIELD_EX64(env->msr, MSR, IR)
1239                                       : !FIELD_EX64(env->msr, MSR, DR)) {
1240         *raddrp = eaddr;
1241         *protp = PAGE_RWX;
1242         *psizep = TARGET_PAGE_BITS;
1243         return true;
1244     } else if (env->mmu_model == POWERPC_MMU_REAL) {
1245         cpu_abort(CPU(cpu), "PowerPC in real mode shold not do translation\n");
1246     }
1247     return false;
1248 }
1249 
1250 static bool ppc_40x_xlate(PowerPCCPU *cpu, vaddr eaddr,
1251                           MMUAccessType access_type,
1252                           hwaddr *raddrp, int *psizep, int *protp,
1253                           int mmu_idx, bool guest_visible)
1254 {
1255     CPUState *cs = CPU(cpu);
1256     CPUPPCState *env = &cpu->env;
1257     int ret;
1258 
1259     if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
1260         return true;
1261     }
1262 
1263     ret = mmu40x_get_physical_address(env, raddrp, protp, eaddr, access_type);
1264     if (ret == 0) {
1265         *psizep = TARGET_PAGE_BITS;
1266         return true;
1267     } else if (!guest_visible) {
1268         return false;
1269     }
1270 
1271     log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
1272     if (access_type == MMU_INST_FETCH) {
1273         switch (ret) {
1274         case -1:
1275             /* No matches in page tables or TLB */
1276             cs->exception_index = POWERPC_EXCP_ITLB;
1277             env->error_code = 0;
1278             env->spr[SPR_40x_DEAR] = eaddr;
1279             env->spr[SPR_40x_ESR] = 0x00000000;
1280             break;
1281         case -2:
1282             /* Access rights violation */
1283             cs->exception_index = POWERPC_EXCP_ISI;
1284             env->error_code = 0x08000000;
1285             break;
1286         default:
1287             g_assert_not_reached();
1288         }
1289     } else {
1290         switch (ret) {
1291         case -1:
1292             /* No matches in page tables or TLB */
1293             cs->exception_index = POWERPC_EXCP_DTLB;
1294             env->error_code = 0;
1295             env->spr[SPR_40x_DEAR] = eaddr;
1296             if (access_type == MMU_DATA_STORE) {
1297                 env->spr[SPR_40x_ESR] = 0x00800000;
1298             } else {
1299                 env->spr[SPR_40x_ESR] = 0x00000000;
1300             }
1301             break;
1302         case -2:
1303             /* Access rights violation */
1304             cs->exception_index = POWERPC_EXCP_DSI;
1305             env->error_code = 0;
1306             env->spr[SPR_40x_DEAR] = eaddr;
1307             if (access_type == MMU_DATA_STORE) {
1308                 env->spr[SPR_40x_ESR] |= 0x00800000;
1309             }
1310             break;
1311         default:
1312             g_assert_not_reached();
1313         }
1314     }
1315     return false;
1316 }
1317 
1318 static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
1319                           MMUAccessType access_type,
1320                           hwaddr *raddrp, int *psizep, int *protp,
1321                           int mmu_idx, bool guest_visible)
1322 {
1323     CPUState *cs = CPU(cpu);
1324     CPUPPCState *env = &cpu->env;
1325     mmu_ctx_t ctx;
1326     int type;
1327     int ret;
1328 
1329     if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
1330         return true;
1331     }
1332 
1333     if (access_type == MMU_INST_FETCH) {
1334         /* code access */
1335         type = ACCESS_CODE;
1336     } else if (guest_visible) {
1337         /* data access */
1338         type = env->access_type;
1339     } else {
1340         type = ACCESS_INT;
1341     }
1342 
1343     ctx.prot = 0;
1344     ctx.hash[0] = 0;
1345     ctx.hash[1] = 0;
1346     ret = mmu6xx_get_physical_address(env, &ctx, eaddr, access_type, type);
1347     if (ret == 0) {
1348         *raddrp = ctx.raddr;
1349         *protp = ctx.prot;
1350         *psizep = TARGET_PAGE_BITS;
1351         return true;
1352     } else if (!guest_visible) {
1353         return false;
1354     }
1355 
1356     log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
1357     if (type == ACCESS_CODE) {
1358         switch (ret) {
1359         case -1:
1360             /* No matches in page tables or TLB */
1361             cs->exception_index = POWERPC_EXCP_IFTLB;
1362             env->error_code = 1 << 18;
1363             env->spr[SPR_IMISS] = eaddr;
1364             env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1365             goto tlb_miss;
1366         case -2:
1367             /* Access rights violation */
1368             cs->exception_index = POWERPC_EXCP_ISI;
1369             env->error_code = 0x08000000;
1370             break;
1371         case -3:
1372             /* No execute protection violation */
1373             cs->exception_index = POWERPC_EXCP_ISI;
1374             env->error_code = 0x10000000;
1375             break;
1376         case -4:
1377             /* Direct store exception */
1378             /* No code fetch is allowed in direct-store areas */
1379             cs->exception_index = POWERPC_EXCP_ISI;
1380             env->error_code = 0x10000000;
1381             break;
1382         }
1383     } else {
1384         switch (ret) {
1385         case -1:
1386             /* No matches in page tables or TLB */
1387             if (access_type == MMU_DATA_STORE) {
1388                 cs->exception_index = POWERPC_EXCP_DSTLB;
1389                 env->error_code = 1 << 16;
1390             } else {
1391                 cs->exception_index = POWERPC_EXCP_DLTLB;
1392                 env->error_code = 0;
1393             }
1394             env->spr[SPR_DMISS] = eaddr;
1395             env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1396 tlb_miss:
1397             env->error_code |= ctx.key << 19;
1398             env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
1399                                   get_pteg_offset32(cpu, ctx.hash[0]);
1400             env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
1401                                   get_pteg_offset32(cpu, ctx.hash[1]);
1402             break;
1403         case -2:
1404             /* Access rights violation */
1405             cs->exception_index = POWERPC_EXCP_DSI;
1406             env->error_code = 0;
1407             env->spr[SPR_DAR] = eaddr;
1408             if (access_type == MMU_DATA_STORE) {
1409                 env->spr[SPR_DSISR] = 0x0A000000;
1410             } else {
1411                 env->spr[SPR_DSISR] = 0x08000000;
1412             }
1413             break;
1414         case -4:
1415             /* Direct store exception */
1416             switch (type) {
1417             case ACCESS_FLOAT:
1418                 /* Floating point load/store */
1419                 cs->exception_index = POWERPC_EXCP_ALIGN;
1420                 env->error_code = POWERPC_EXCP_ALIGN_FP;
1421                 env->spr[SPR_DAR] = eaddr;
1422                 break;
1423             case ACCESS_RES:
1424                 /* lwarx, ldarx or stwcx. */
1425                 cs->exception_index = POWERPC_EXCP_DSI;
1426                 env->error_code = 0;
1427                 env->spr[SPR_DAR] = eaddr;
1428                 if (access_type == MMU_DATA_STORE) {
1429                     env->spr[SPR_DSISR] = 0x06000000;
1430                 } else {
1431                     env->spr[SPR_DSISR] = 0x04000000;
1432                 }
1433                 break;
1434             case ACCESS_EXT:
1435                 /* eciwx or ecowx */
1436                 cs->exception_index = POWERPC_EXCP_DSI;
1437                 env->error_code = 0;
1438                 env->spr[SPR_DAR] = eaddr;
1439                 if (access_type == MMU_DATA_STORE) {
1440                     env->spr[SPR_DSISR] = 0x06100000;
1441                 } else {
1442                     env->spr[SPR_DSISR] = 0x04100000;
1443                 }
1444                 break;
1445             default:
1446                 printf("DSI: invalid exception (%d)\n", ret);
1447                 cs->exception_index = POWERPC_EXCP_PROGRAM;
1448                 env->error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1449                 env->spr[SPR_DAR] = eaddr;
1450                 break;
1451             }
1452             break;
1453         }
1454     }
1455     return false;
1456 }
1457 
1458 /*****************************************************************************/
1459 
1460 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
1461                       hwaddr *raddrp, int *psizep, int *protp,
1462                       int mmu_idx, bool guest_visible)
1463 {
1464     switch (cpu->env.mmu_model) {
1465 #if defined(TARGET_PPC64)
1466     case POWERPC_MMU_3_00:
1467         if (ppc64_v3_radix(cpu)) {
1468             return ppc_radix64_xlate(cpu, eaddr, access_type, raddrp,
1469                                      psizep, protp, mmu_idx, guest_visible);
1470         }
1471         /* fall through */
1472     case POWERPC_MMU_64B:
1473     case POWERPC_MMU_2_03:
1474     case POWERPC_MMU_2_06:
1475     case POWERPC_MMU_2_07:
1476         return ppc_hash64_xlate(cpu, eaddr, access_type,
1477                                 raddrp, psizep, protp, mmu_idx, guest_visible);
1478 #endif
1479 
1480     case POWERPC_MMU_32B:
1481         return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp,
1482                                psizep, protp, mmu_idx, guest_visible);
1483     case POWERPC_MMU_BOOKE:
1484     case POWERPC_MMU_BOOKE206:
1485         return ppc_booke_xlate(cpu, eaddr, access_type, raddrp,
1486                                psizep, protp, mmu_idx, guest_visible);
1487     case POWERPC_MMU_SOFT_4xx:
1488         return ppc_40x_xlate(cpu, eaddr, access_type, raddrp,
1489                              psizep, protp, mmu_idx, guest_visible);
1490     case POWERPC_MMU_SOFT_6xx:
1491         return ppc_6xx_xlate(cpu, eaddr, access_type, raddrp,
1492                              psizep, protp, mmu_idx, guest_visible);
1493     case POWERPC_MMU_REAL:
1494         return ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep,
1495                                    protp);
1496     case POWERPC_MMU_MPC8xx:
1497         cpu_abort(env_cpu(&cpu->env), "MPC8xx MMU model is not implemented\n");
1498     default:
1499         cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n");
1500     }
1501 }
1502 
1503 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
1504 {
1505     PowerPCCPU *cpu = POWERPC_CPU(cs);
1506     hwaddr raddr;
1507     int s, p;
1508 
1509     /*
1510      * Some MMUs have separate TLBs for code and data. If we only
1511      * try an MMU_DATA_LOAD, we may not be able to read instructions
1512      * mapped by code TLBs, so we also try a MMU_INST_FETCH.
1513      */
1514     if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p,
1515                   ppc_env_mmu_index(&cpu->env, false), false) ||
1516         ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p,
1517                   ppc_env_mmu_index(&cpu->env, true), false)) {
1518         return raddr & TARGET_PAGE_MASK;
1519     }
1520     return -1;
1521 }
1522