xref: /openbmc/qemu/target/ppc/mmu_helper.c (revision 3979fca4)
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 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 #include "qemu/osdep.h"
20 #include "qemu/units.h"
21 #include "cpu.h"
22 #include "exec/helper-proto.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/cpu_ldst.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 "mmu-book3s-v3.h"
34 #include "mmu-radix64.h"
35 
36 //#define DEBUG_MMU
37 //#define DEBUG_BATS
38 //#define DEBUG_SOFTWARE_TLB
39 //#define DUMP_PAGE_TABLES
40 //#define FLUSH_ALL_TLBS
41 
42 #ifdef DEBUG_MMU
43 #  define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0)
44 #else
45 #  define LOG_MMU_STATE(cpu) do { } while (0)
46 #endif
47 
48 #ifdef DEBUG_SOFTWARE_TLB
49 #  define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
50 #else
51 #  define LOG_SWTLB(...) do { } while (0)
52 #endif
53 
54 #ifdef DEBUG_BATS
55 #  define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
56 #else
57 #  define LOG_BATS(...) do { } while (0)
58 #endif
59 
60 /*****************************************************************************/
61 /* PowerPC MMU emulation */
62 
63 /* Context used internally during MMU translations */
64 typedef struct mmu_ctx_t mmu_ctx_t;
65 struct mmu_ctx_t {
66     hwaddr raddr;      /* Real address              */
67     hwaddr eaddr;      /* Effective address         */
68     int prot;                      /* Protection bits           */
69     hwaddr hash[2];    /* Pagetable hash values     */
70     target_ulong ptem;             /* Virtual segment ID | API  */
71     int key;                       /* Access key                */
72     int nx;                        /* Non-execute area          */
73 };
74 
75 /* Common routines used by software and hardware TLBs emulation */
76 static inline int pte_is_valid(target_ulong pte0)
77 {
78     return pte0 & 0x80000000 ? 1 : 0;
79 }
80 
81 static inline void pte_invalidate(target_ulong *pte0)
82 {
83     *pte0 &= ~0x80000000;
84 }
85 
86 #define PTE_PTEM_MASK 0x7FFFFFBF
87 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
88 
89 static int pp_check(int key, int pp, int nx)
90 {
91     int access;
92 
93     /* Compute access rights */
94     access = 0;
95     if (key == 0) {
96         switch (pp) {
97         case 0x0:
98         case 0x1:
99         case 0x2:
100             access |= PAGE_WRITE;
101             /* No break here */
102         case 0x3:
103             access |= PAGE_READ;
104             break;
105         }
106     } else {
107         switch (pp) {
108         case 0x0:
109             access = 0;
110             break;
111         case 0x1:
112         case 0x3:
113             access = PAGE_READ;
114             break;
115         case 0x2:
116             access = PAGE_READ | PAGE_WRITE;
117             break;
118         }
119     }
120     if (nx == 0) {
121         access |= PAGE_EXEC;
122     }
123 
124     return access;
125 }
126 
127 static int check_prot(int prot, int rw, int access_type)
128 {
129     int ret;
130 
131     if (access_type == ACCESS_CODE) {
132         if (prot & PAGE_EXEC) {
133             ret = 0;
134         } else {
135             ret = -2;
136         }
137     } else if (rw) {
138         if (prot & PAGE_WRITE) {
139             ret = 0;
140         } else {
141             ret = -2;
142         }
143     } else {
144         if (prot & PAGE_READ) {
145             ret = 0;
146         } else {
147             ret = -2;
148         }
149     }
150 
151     return ret;
152 }
153 
154 static inline int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
155                                        target_ulong pte1, int h, int rw, int type)
156 {
157     target_ulong ptem, mmask;
158     int access, ret, pteh, ptev, pp;
159 
160     ret = -1;
161     /* Check validity and table match */
162     ptev = pte_is_valid(pte0);
163     pteh = (pte0 >> 6) & 1;
164     if (ptev && h == pteh) {
165         /* Check vsid & api */
166         ptem = pte0 & PTE_PTEM_MASK;
167         mmask = PTE_CHECK_MASK;
168         pp = pte1 & 0x00000003;
169         if (ptem == ctx->ptem) {
170             if (ctx->raddr != (hwaddr)-1ULL) {
171                 /* all matches should have equal RPN, WIMG & PP */
172                 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
173                     qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
174                     return -3;
175                 }
176             }
177             /* Compute access rights */
178             access = pp_check(ctx->key, pp, ctx->nx);
179             /* Keep the matching PTE informations */
180             ctx->raddr = pte1;
181             ctx->prot = access;
182             ret = check_prot(ctx->prot, rw, type);
183             if (ret == 0) {
184                 /* Access granted */
185                 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
186             } else {
187                 /* Access right violation */
188                 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
189             }
190         }
191     }
192 
193     return ret;
194 }
195 
196 static int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
197                             int ret, int rw)
198 {
199     int store = 0;
200 
201     /* Update page flags */
202     if (!(*pte1p & 0x00000100)) {
203         /* Update accessed flag */
204         *pte1p |= 0x00000100;
205         store = 1;
206     }
207     if (!(*pte1p & 0x00000080)) {
208         if (rw == 1 && ret == 0) {
209             /* Update changed flag */
210             *pte1p |= 0x00000080;
211             store = 1;
212         } else {
213             /* Force page fault for first write access */
214             ctx->prot &= ~PAGE_WRITE;
215         }
216     }
217 
218     return store;
219 }
220 
221 /* Software driven TLB helpers */
222 static inline int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
223                                     int way, int is_code)
224 {
225     int nr;
226 
227     /* Select TLB num in a way from address */
228     nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
229     /* Select TLB way */
230     nr += env->tlb_per_way * way;
231     /* 6xx have separate TLBs for instructions and data */
232     if (is_code && env->id_tlbs == 1) {
233         nr += env->nb_tlb;
234     }
235 
236     return nr;
237 }
238 
239 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState *env)
240 {
241     PowerPCCPU *cpu = ppc_env_get_cpu(env);
242     ppc6xx_tlb_t *tlb;
243     int nr, max;
244 
245     /* LOG_SWTLB("Invalidate all TLBs\n"); */
246     /* Invalidate all defined software TLB */
247     max = env->nb_tlb;
248     if (env->id_tlbs == 1) {
249         max *= 2;
250     }
251     for (nr = 0; nr < max; nr++) {
252         tlb = &env->tlb.tlb6[nr];
253         pte_invalidate(&tlb->pte0);
254     }
255     tlb_flush(CPU(cpu));
256 }
257 
258 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState *env,
259                                                target_ulong eaddr,
260                                                int is_code, int match_epn)
261 {
262 #if !defined(FLUSH_ALL_TLBS)
263     CPUState *cs = CPU(ppc_env_get_cpu(env));
264     ppc6xx_tlb_t *tlb;
265     int way, nr;
266 
267     /* Invalidate ITLB + DTLB, all ways */
268     for (way = 0; way < env->nb_ways; way++) {
269         nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
270         tlb = &env->tlb.tlb6[nr];
271         if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
272             LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
273                       env->nb_tlb, eaddr);
274             pte_invalidate(&tlb->pte0);
275             tlb_flush_page(cs, tlb->EPN);
276         }
277     }
278 #else
279     /* XXX: PowerPC specification say this is valid as well */
280     ppc6xx_tlb_invalidate_all(env);
281 #endif
282 }
283 
284 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState *env,
285                                               target_ulong eaddr, int is_code)
286 {
287     ppc6xx_tlb_invalidate_virt2(env, eaddr, is_code, 0);
288 }
289 
290 static void ppc6xx_tlb_store(CPUPPCState *env, target_ulong EPN, int way,
291                              int is_code, target_ulong pte0, target_ulong pte1)
292 {
293     ppc6xx_tlb_t *tlb;
294     int nr;
295 
296     nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
297     tlb = &env->tlb.tlb6[nr];
298     LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
299               " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
300     /* Invalidate any pending reference in QEMU for this virtual address */
301     ppc6xx_tlb_invalidate_virt2(env, EPN, is_code, 1);
302     tlb->pte0 = pte0;
303     tlb->pte1 = pte1;
304     tlb->EPN = EPN;
305     /* Store last way for LRU mechanism */
306     env->last_way = way;
307 }
308 
309 static inline int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
310                                    target_ulong eaddr, int rw, int access_type)
311 {
312     ppc6xx_tlb_t *tlb;
313     int nr, best, way;
314     int ret;
315 
316     best = -1;
317     ret = -1; /* No TLB found */
318     for (way = 0; way < env->nb_ways; way++) {
319         nr = ppc6xx_tlb_getnum(env, eaddr, way,
320                                access_type == ACCESS_CODE ? 1 : 0);
321         tlb = &env->tlb.tlb6[nr];
322         /* This test "emulates" the PTE index match for hardware TLBs */
323         if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
324             LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
325                       "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
326                       pte_is_valid(tlb->pte0) ? "valid" : "inval",
327                       tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
328             continue;
329         }
330         LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
331                   TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
332                   pte_is_valid(tlb->pte0) ? "valid" : "inval",
333                   tlb->EPN, eaddr, tlb->pte1,
334                   rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
335         switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
336         case -3:
337             /* TLB inconsistency */
338             return -1;
339         case -2:
340             /* Access violation */
341             ret = -2;
342             best = nr;
343             break;
344         case -1:
345         default:
346             /* No match */
347             break;
348         case 0:
349             /* access granted */
350             /* XXX: we should go on looping to check all TLBs consistency
351              *      but we can speed-up the whole thing as the
352              *      result would be undefined if TLBs are not consistent.
353              */
354             ret = 0;
355             best = nr;
356             goto done;
357         }
358     }
359     if (best != -1) {
360     done:
361         LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
362                   ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
363         /* Update page flags */
364         pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, rw);
365     }
366 
367     return ret;
368 }
369 
370 /* Perform BAT hit & translation */
371 static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
372                                  int *validp, int *protp, target_ulong *BATu,
373                                  target_ulong *BATl)
374 {
375     target_ulong bl;
376     int pp, valid, prot;
377 
378     bl = (*BATu & 0x00001FFC) << 15;
379     valid = 0;
380     prot = 0;
381     if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
382         ((msr_pr != 0) && (*BATu & 0x00000001))) {
383         valid = 1;
384         pp = *BATl & 0x00000003;
385         if (pp != 0) {
386             prot = PAGE_READ | PAGE_EXEC;
387             if (pp == 0x2) {
388                 prot |= PAGE_WRITE;
389             }
390         }
391     }
392     *blp = bl;
393     *validp = valid;
394     *protp = prot;
395 }
396 
397 static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
398                            target_ulong virtual, int rw, int type)
399 {
400     target_ulong *BATlt, *BATut, *BATu, *BATl;
401     target_ulong BEPIl, BEPIu, bl;
402     int i, valid, prot;
403     int ret = -1;
404 
405     LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
406              type == ACCESS_CODE ? 'I' : 'D', virtual);
407     switch (type) {
408     case ACCESS_CODE:
409         BATlt = env->IBAT[1];
410         BATut = env->IBAT[0];
411         break;
412     default:
413         BATlt = env->DBAT[1];
414         BATut = env->DBAT[0];
415         break;
416     }
417     for (i = 0; i < env->nb_BATs; i++) {
418         BATu = &BATut[i];
419         BATl = &BATlt[i];
420         BEPIu = *BATu & 0xF0000000;
421         BEPIl = *BATu & 0x0FFE0000;
422         bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
423         LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
424                  " BATl " TARGET_FMT_lx "\n", __func__,
425                  type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
426         if ((virtual & 0xF0000000) == BEPIu &&
427             ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
428             /* BAT matches */
429             if (valid != 0) {
430                 /* Get physical address */
431                 ctx->raddr = (*BATl & 0xF0000000) |
432                     ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
433                     (virtual & 0x0001F000);
434                 /* Compute access rights */
435                 ctx->prot = prot;
436                 ret = check_prot(ctx->prot, rw, type);
437                 if (ret == 0) {
438                     LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
439                              i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
440                              ctx->prot & PAGE_WRITE ? 'W' : '-');
441                 }
442                 break;
443             }
444         }
445     }
446     if (ret < 0) {
447 #if defined(DEBUG_BATS)
448         if (qemu_log_enabled()) {
449             LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
450             for (i = 0; i < 4; i++) {
451                 BATu = &BATut[i];
452                 BATl = &BATlt[i];
453                 BEPIu = *BATu & 0xF0000000;
454                 BEPIl = *BATu & 0x0FFE0000;
455                 bl = (*BATu & 0x00001FFC) << 15;
456                 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
457                          " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
458                          TARGET_FMT_lx " " TARGET_FMT_lx "\n",
459                          __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
460                          *BATu, *BATl, BEPIu, BEPIl, bl);
461             }
462         }
463 #endif
464     }
465     /* No hit */
466     return ret;
467 }
468 
469 /* Perform segment based translation */
470 static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
471                                       target_ulong eaddr, int rw, int type)
472 {
473     PowerPCCPU *cpu = ppc_env_get_cpu(env);
474     hwaddr hash;
475     target_ulong vsid;
476     int ds, pr, target_page_bits;
477     int ret;
478     target_ulong sr, pgidx;
479 
480     pr = msr_pr;
481     ctx->eaddr = eaddr;
482 
483     sr = env->sr[eaddr >> 28];
484     ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
485                 ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
486     ds = sr & 0x80000000 ? 1 : 0;
487     ctx->nx = sr & 0x10000000 ? 1 : 0;
488     vsid = sr & 0x00FFFFFF;
489     target_page_bits = TARGET_PAGE_BITS;
490     qemu_log_mask(CPU_LOG_MMU,
491             "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
492             " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
493             " ir=%d dr=%d pr=%d %d t=%d\n",
494             eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
495             (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
496     pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
497     hash = vsid ^ pgidx;
498     ctx->ptem = (vsid << 7) | (pgidx >> 10);
499 
500     qemu_log_mask(CPU_LOG_MMU,
501             "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
502             ctx->key, ds, ctx->nx, vsid);
503     ret = -1;
504     if (!ds) {
505         /* Check if instruction fetch is allowed, if needed */
506         if (type != ACCESS_CODE || ctx->nx == 0) {
507             /* Page address translation */
508             qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx
509                     " htab_mask " TARGET_FMT_plx
510                     " hash " TARGET_FMT_plx "\n",
511                     ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
512             ctx->hash[0] = hash;
513             ctx->hash[1] = ~hash;
514 
515             /* Initialize real address with an invalid value */
516             ctx->raddr = (hwaddr)-1ULL;
517             /* Software TLB search */
518             ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
519 #if defined(DUMP_PAGE_TABLES)
520             if (qemu_loglevel_mask(CPU_LOG_MMU)) {
521                 CPUState *cs = ENV_GET_CPU(env);
522                 hwaddr curaddr;
523                 uint32_t a0, a1, a2, a3;
524 
525                 qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
526                          "\n", ppc_hash32_hpt_base(cpu),
527                          ppc_hash32_hpt_mask(env) + 0x80);
528                 for (curaddr = ppc_hash32_hpt_base(cpu);
529                      curaddr < (ppc_hash32_hpt_base(cpu)
530                                 + ppc_hash32_hpt_mask(cpu) + 0x80);
531                      curaddr += 16) {
532                     a0 = ldl_phys(cs->as, curaddr);
533                     a1 = ldl_phys(cs->as, curaddr + 4);
534                     a2 = ldl_phys(cs->as, curaddr + 8);
535                     a3 = ldl_phys(cs->as, curaddr + 12);
536                     if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
537                         qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
538                                  curaddr, a0, a1, a2, a3);
539                     }
540                 }
541             }
542 #endif
543         } else {
544             qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
545             ret = -3;
546         }
547     } else {
548         target_ulong sr;
549 
550         qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
551         /* Direct-store segment : absolutely *BUGGY* for now */
552 
553         /* Direct-store implies a 32-bit MMU.
554          * Check the Segment Register's bus unit ID (BUID).
555          */
556         sr = env->sr[eaddr >> 28];
557         if ((sr & 0x1FF00000) >> 20 == 0x07f) {
558             /* Memory-forced I/O controller interface access */
559             /* If T=1 and BUID=x'07F', the 601 performs a memory access
560              * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
561              */
562             ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
563             ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
564             return 0;
565         }
566 
567         switch (type) {
568         case ACCESS_INT:
569             /* Integer load/store : only access allowed */
570             break;
571         case ACCESS_CODE:
572             /* No code fetch is allowed in direct-store areas */
573             return -4;
574         case ACCESS_FLOAT:
575             /* Floating point load/store */
576             return -4;
577         case ACCESS_RES:
578             /* lwarx, ldarx or srwcx. */
579             return -4;
580         case ACCESS_CACHE:
581             /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
582             /* Should make the instruction do no-op.
583              * As it already do no-op, it's quite easy :-)
584              */
585             ctx->raddr = eaddr;
586             return 0;
587         case ACCESS_EXT:
588             /* eciwx or ecowx */
589             return -4;
590         default:
591             qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need "
592                           "address translation\n");
593             return -4;
594         }
595         if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
596             ctx->raddr = eaddr;
597             ret = 2;
598         } else {
599             ret = -2;
600         }
601     }
602 
603     return ret;
604 }
605 
606 /* Generic TLB check function for embedded PowerPC implementations */
607 static int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
608                             hwaddr *raddrp,
609                             target_ulong address, uint32_t pid, int ext,
610                             int i)
611 {
612     target_ulong mask;
613 
614     /* Check valid flag */
615     if (!(tlb->prot & PAGE_VALID)) {
616         return -1;
617     }
618     mask = ~(tlb->size - 1);
619     LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
620               " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
621               mask, (uint32_t)tlb->PID, tlb->prot);
622     /* Check PID */
623     if (tlb->PID != 0 && tlb->PID != pid) {
624         return -1;
625     }
626     /* Check effective address */
627     if ((address & mask) != tlb->EPN) {
628         return -1;
629     }
630     *raddrp = (tlb->RPN & mask) | (address & ~mask);
631     if (ext) {
632         /* Extend the physical address to 36 bits */
633         *raddrp |= (uint64_t)(tlb->RPN & 0xF) << 32;
634     }
635 
636     return 0;
637 }
638 
639 /* Generic TLB search function for PowerPC embedded implementations */
640 static int ppcemb_tlb_search(CPUPPCState *env, target_ulong address,
641                              uint32_t pid)
642 {
643     ppcemb_tlb_t *tlb;
644     hwaddr raddr;
645     int i, ret;
646 
647     /* Default return value is no match */
648     ret = -1;
649     for (i = 0; i < env->nb_tlb; i++) {
650         tlb = &env->tlb.tlbe[i];
651         if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
652             ret = i;
653             break;
654         }
655     }
656 
657     return ret;
658 }
659 
660 /* Helpers specific to PowerPC 40x implementations */
661 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState *env)
662 {
663     PowerPCCPU *cpu = ppc_env_get_cpu(env);
664     ppcemb_tlb_t *tlb;
665     int i;
666 
667     for (i = 0; i < env->nb_tlb; i++) {
668         tlb = &env->tlb.tlbe[i];
669         tlb->prot &= ~PAGE_VALID;
670     }
671     tlb_flush(CPU(cpu));
672 }
673 
674 static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
675                                        target_ulong address, int rw,
676                                        int access_type)
677 {
678     ppcemb_tlb_t *tlb;
679     hwaddr raddr;
680     int i, ret, zsel, zpr, pr;
681 
682     ret = -1;
683     raddr = (hwaddr)-1ULL;
684     pr = msr_pr;
685     for (i = 0; i < env->nb_tlb; i++) {
686         tlb = &env->tlb.tlbe[i];
687         if (ppcemb_tlb_check(env, tlb, &raddr, address,
688                              env->spr[SPR_40x_PID], 0, i) < 0) {
689             continue;
690         }
691         zsel = (tlb->attr >> 4) & 0xF;
692         zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
693         LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
694                     __func__, i, zsel, zpr, rw, tlb->attr);
695         /* Check execute enable bit */
696         switch (zpr) {
697         case 0x2:
698             if (pr != 0) {
699                 goto check_perms;
700             }
701             /* No break here */
702         case 0x3:
703             /* All accesses granted */
704             ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
705             ret = 0;
706             break;
707         case 0x0:
708             if (pr != 0) {
709                 /* Raise Zone protection fault.  */
710                 env->spr[SPR_40x_ESR] = 1 << 22;
711                 ctx->prot = 0;
712                 ret = -2;
713                 break;
714             }
715             /* No break here */
716         case 0x1:
717         check_perms:
718             /* Check from TLB entry */
719             ctx->prot = tlb->prot;
720             ret = check_prot(ctx->prot, rw, access_type);
721             if (ret == -2) {
722                 env->spr[SPR_40x_ESR] = 0;
723             }
724             break;
725         }
726         if (ret >= 0) {
727             ctx->raddr = raddr;
728             LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
729                       " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
730                       ret);
731             return 0;
732         }
733     }
734     LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
735               " %d %d\n", __func__, address, raddr, ctx->prot, ret);
736 
737     return ret;
738 }
739 
740 void store_40x_sler(CPUPPCState *env, uint32_t val)
741 {
742     PowerPCCPU *cpu = ppc_env_get_cpu(env);
743 
744     /* XXX: TO BE FIXED */
745     if (val != 0x00000000) {
746         cpu_abort(CPU(cpu), "Little-endian regions are not supported by now\n");
747     }
748     env->spr[SPR_405_SLER] = val;
749 }
750 
751 static inline int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb,
752                                      hwaddr *raddr, int *prot,
753                                      target_ulong address, int rw,
754                                      int access_type, int i)
755 {
756     int ret, prot2;
757 
758     if (ppcemb_tlb_check(env, tlb, raddr, address,
759                          env->spr[SPR_BOOKE_PID],
760                          !env->nb_pids, i) >= 0) {
761         goto found_tlb;
762     }
763 
764     if (env->spr[SPR_BOOKE_PID1] &&
765         ppcemb_tlb_check(env, tlb, raddr, address,
766                          env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
767         goto found_tlb;
768     }
769 
770     if (env->spr[SPR_BOOKE_PID2] &&
771         ppcemb_tlb_check(env, tlb, raddr, address,
772                          env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
773         goto found_tlb;
774     }
775 
776     LOG_SWTLB("%s: TLB entry not found\n", __func__);
777     return -1;
778 
779 found_tlb:
780 
781     if (msr_pr != 0) {
782         prot2 = tlb->prot & 0xF;
783     } else {
784         prot2 = (tlb->prot >> 4) & 0xF;
785     }
786 
787     /* Check the address space */
788     if (access_type == ACCESS_CODE) {
789         if (msr_ir != (tlb->attr & 1)) {
790             LOG_SWTLB("%s: AS doesn't match\n", __func__);
791             return -1;
792         }
793 
794         *prot = prot2;
795         if (prot2 & PAGE_EXEC) {
796             LOG_SWTLB("%s: good TLB!\n", __func__);
797             return 0;
798         }
799 
800         LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, prot2);
801         ret = -3;
802     } else {
803         if (msr_dr != (tlb->attr & 1)) {
804             LOG_SWTLB("%s: AS doesn't match\n", __func__);
805             return -1;
806         }
807 
808         *prot = prot2;
809         if ((!rw && prot2 & PAGE_READ) || (rw && (prot2 & PAGE_WRITE))) {
810             LOG_SWTLB("%s: found TLB!\n", __func__);
811             return 0;
812         }
813 
814         LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, prot2);
815         ret = -2;
816     }
817 
818     return ret;
819 }
820 
821 static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
822                                          target_ulong address, int rw,
823                                          int access_type)
824 {
825     ppcemb_tlb_t *tlb;
826     hwaddr raddr;
827     int i, ret;
828 
829     ret = -1;
830     raddr = (hwaddr)-1ULL;
831     for (i = 0; i < env->nb_tlb; i++) {
832         tlb = &env->tlb.tlbe[i];
833         ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
834                                  access_type, i);
835         if (ret != -1) {
836             break;
837         }
838     }
839 
840     if (ret >= 0) {
841         ctx->raddr = raddr;
842         LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
843                   " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
844                   ret);
845     } else {
846         LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
847                   " %d %d\n", __func__, address, raddr, ctx->prot, ret);
848     }
849 
850     return ret;
851 }
852 
853 static void booke206_flush_tlb(CPUPPCState *env, int flags,
854                                const int check_iprot)
855 {
856     PowerPCCPU *cpu = ppc_env_get_cpu(env);
857     int tlb_size;
858     int i, j;
859     ppcmas_tlb_t *tlb = env->tlb.tlbm;
860 
861     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
862         if (flags & (1 << i)) {
863             tlb_size = booke206_tlb_size(env, i);
864             for (j = 0; j < tlb_size; j++) {
865                 if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) {
866                     tlb[j].mas1 &= ~MAS1_VALID;
867                 }
868             }
869         }
870         tlb += booke206_tlb_size(env, i);
871     }
872 
873     tlb_flush(CPU(cpu));
874 }
875 
876 static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
877                                         ppcmas_tlb_t *tlb)
878 {
879     int tlbm_size;
880 
881     tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
882 
883     return 1024ULL << tlbm_size;
884 }
885 
886 /* TLB check function for MAS based SoftTLBs */
887 static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
888                             hwaddr *raddrp, target_ulong address,
889                             uint32_t pid)
890 {
891     hwaddr mask;
892     uint32_t tlb_pid;
893 
894     if (!msr_cm) {
895         /* In 32bit mode we can only address 32bit EAs */
896         address = (uint32_t)address;
897     }
898 
899     /* Check valid flag */
900     if (!(tlb->mas1 & MAS1_VALID)) {
901         return -1;
902     }
903 
904     mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
905     LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
906               PRIx64 " mask=0x%" HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%"
907               PRIx32 "\n", __func__, address, pid, tlb->mas1, tlb->mas2, mask,
908               tlb->mas7_3, tlb->mas8);
909 
910     /* Check PID */
911     tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
912     if (tlb_pid != 0 && tlb_pid != pid) {
913         return -1;
914     }
915 
916     /* Check effective address */
917     if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
918         return -1;
919     }
920 
921     if (raddrp) {
922         *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
923     }
924 
925     return 0;
926 }
927 
928 static bool is_epid_mmu(int mmu_idx)
929 {
930     return mmu_idx == PPC_TLB_EPID_STORE || mmu_idx == PPC_TLB_EPID_LOAD;
931 }
932 
933 static uint32_t mmubooke206_esr(int mmu_idx, bool rw)
934 {
935     uint32_t esr = 0;
936     if (rw) {
937         esr |= ESR_ST;
938     }
939     if (is_epid_mmu(mmu_idx)) {
940         esr |= ESR_EPID;
941     }
942     return esr;
943 }
944 
945 /* Get EPID register given the mmu_idx. If this is regular load,
946  * construct the EPID access bits from current processor state  */
947 
948 /* Get the effective AS and PR bits and the PID. The PID is returned only if
949  * EPID load is requested, otherwise the caller must detect the correct EPID.
950  * Return true if valid EPID is returned. */
951 static bool mmubooke206_get_as(CPUPPCState *env,
952                                int mmu_idx, uint32_t *epid_out,
953                                bool *as_out, bool *pr_out)
954 {
955     if (is_epid_mmu(mmu_idx)) {
956         uint32_t epidr;
957         if (mmu_idx == PPC_TLB_EPID_STORE) {
958             epidr = env->spr[SPR_BOOKE_EPSC];
959         } else {
960             epidr = env->spr[SPR_BOOKE_EPLC];
961         }
962         *epid_out = (epidr & EPID_EPID) >> EPID_EPID_SHIFT;
963         *as_out = !!(epidr & EPID_EAS);
964         *pr_out = !!(epidr & EPID_EPR);
965         return true;
966     } else {
967         *as_out = msr_ds;
968         *pr_out = msr_pr;
969         return false;
970     }
971 }
972 
973 /* Check if the tlb found by hashing really matches */
974 static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
975                                  hwaddr *raddr, int *prot,
976                                  target_ulong address, int rw,
977                                  int access_type, int mmu_idx)
978 {
979     int ret;
980     int prot2 = 0;
981     uint32_t epid;
982     bool as, pr;
983     bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
984 
985     if (!use_epid) {
986         if (ppcmas_tlb_check(env, tlb, raddr, address,
987                              env->spr[SPR_BOOKE_PID]) >= 0) {
988             goto found_tlb;
989         }
990 
991         if (env->spr[SPR_BOOKE_PID1] &&
992             ppcmas_tlb_check(env, tlb, raddr, address,
993                              env->spr[SPR_BOOKE_PID1]) >= 0) {
994             goto found_tlb;
995         }
996 
997         if (env->spr[SPR_BOOKE_PID2] &&
998             ppcmas_tlb_check(env, tlb, raddr, address,
999                              env->spr[SPR_BOOKE_PID2]) >= 0) {
1000             goto found_tlb;
1001         }
1002     } else {
1003         if (ppcmas_tlb_check(env, tlb, raddr, address, epid) >= 0) {
1004             goto found_tlb;
1005         }
1006     }
1007 
1008     LOG_SWTLB("%s: TLB entry not found\n", __func__);
1009     return -1;
1010 
1011 found_tlb:
1012 
1013     if (pr) {
1014         if (tlb->mas7_3 & MAS3_UR) {
1015             prot2 |= PAGE_READ;
1016         }
1017         if (tlb->mas7_3 & MAS3_UW) {
1018             prot2 |= PAGE_WRITE;
1019         }
1020         if (tlb->mas7_3 & MAS3_UX) {
1021             prot2 |= PAGE_EXEC;
1022         }
1023     } else {
1024         if (tlb->mas7_3 & MAS3_SR) {
1025             prot2 |= PAGE_READ;
1026         }
1027         if (tlb->mas7_3 & MAS3_SW) {
1028             prot2 |= PAGE_WRITE;
1029         }
1030         if (tlb->mas7_3 & MAS3_SX) {
1031             prot2 |= PAGE_EXEC;
1032         }
1033     }
1034 
1035     /* Check the address space and permissions */
1036     if (access_type == ACCESS_CODE) {
1037         /* There is no way to fetch code using epid load */
1038         assert(!use_epid);
1039         if (msr_ir != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1040             LOG_SWTLB("%s: AS doesn't match\n", __func__);
1041             return -1;
1042         }
1043 
1044         *prot = prot2;
1045         if (prot2 & PAGE_EXEC) {
1046             LOG_SWTLB("%s: good TLB!\n", __func__);
1047             return 0;
1048         }
1049 
1050         LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, prot2);
1051         ret = -3;
1052     } else {
1053         if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1054             LOG_SWTLB("%s: AS doesn't match\n", __func__);
1055             return -1;
1056         }
1057 
1058         *prot = prot2;
1059         if ((!rw && prot2 & PAGE_READ) || (rw && (prot2 & PAGE_WRITE))) {
1060             LOG_SWTLB("%s: found TLB!\n", __func__);
1061             return 0;
1062         }
1063 
1064         LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, prot2);
1065         ret = -2;
1066     }
1067 
1068     return ret;
1069 }
1070 
1071 static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
1072                                             target_ulong address, int rw,
1073                                             int access_type, int mmu_idx)
1074 {
1075     ppcmas_tlb_t *tlb;
1076     hwaddr raddr;
1077     int i, j, ret;
1078 
1079     ret = -1;
1080     raddr = (hwaddr)-1ULL;
1081 
1082     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1083         int ways = booke206_tlb_ways(env, i);
1084 
1085         for (j = 0; j < ways; j++) {
1086             tlb = booke206_get_tlbm(env, i, address, j);
1087             if (!tlb) {
1088                 continue;
1089             }
1090             ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
1091                                         rw, access_type, mmu_idx);
1092             if (ret != -1) {
1093                 goto found_tlb;
1094             }
1095         }
1096     }
1097 
1098 found_tlb:
1099 
1100     if (ret >= 0) {
1101         ctx->raddr = raddr;
1102         LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1103                   " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1104                   ret);
1105     } else {
1106         LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1107                   " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1108     }
1109 
1110     return ret;
1111 }
1112 
1113 static const char *book3e_tsize_to_str[32] = {
1114     "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1115     "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1116     "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1117     "1T", "2T"
1118 };
1119 
1120 static void mmubooke_dump_mmu(CPUPPCState *env)
1121 {
1122     ppcemb_tlb_t *entry;
1123     int i;
1124 
1125     if (kvm_enabled() && !env->kvm_sw_tlb) {
1126         qemu_printf("Cannot access KVM TLB\n");
1127         return;
1128     }
1129 
1130     qemu_printf("\nTLB:\n");
1131     qemu_printf("Effective          Physical           Size PID   Prot     "
1132                 "Attr\n");
1133 
1134     entry = &env->tlb.tlbe[0];
1135     for (i = 0; i < env->nb_tlb; i++, entry++) {
1136         hwaddr ea, pa;
1137         target_ulong mask;
1138         uint64_t size = (uint64_t)entry->size;
1139         char size_buf[20];
1140 
1141         /* Check valid flag */
1142         if (!(entry->prot & PAGE_VALID)) {
1143             continue;
1144         }
1145 
1146         mask = ~(entry->size - 1);
1147         ea = entry->EPN & mask;
1148         pa = entry->RPN & mask;
1149         /* Extend the physical address to 36 bits */
1150         pa |= (hwaddr)(entry->RPN & 0xF) << 32;
1151         if (size >= 1 * MiB) {
1152             snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB);
1153         } else {
1154             snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB);
1155         }
1156         qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
1157                     (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
1158                     entry->prot, entry->attr);
1159     }
1160 
1161 }
1162 
1163 static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset,
1164                                      int tlbsize)
1165 {
1166     ppcmas_tlb_t *entry;
1167     int i;
1168 
1169     qemu_printf("\nTLB%d:\n", tlbn);
1170     qemu_printf("Effective          Physical           Size TID   TS SRWX"
1171                 " URWX WIMGE U0123\n");
1172 
1173     entry = &env->tlb.tlbm[offset];
1174     for (i = 0; i < tlbsize; i++, entry++) {
1175         hwaddr ea, pa, size;
1176         int tsize;
1177 
1178         if (!(entry->mas1 & MAS1_VALID)) {
1179             continue;
1180         }
1181 
1182         tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1183         size = 1024ULL << tsize;
1184         ea = entry->mas2 & ~(size - 1);
1185         pa = entry->mas7_3 & ~(size - 1);
1186 
1187         qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u  S%c%c%c"
1188                     "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1189                     (uint64_t)ea, (uint64_t)pa,
1190                     book3e_tsize_to_str[tsize],
1191                     (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
1192                     (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
1193                     entry->mas7_3 & MAS3_SR ? 'R' : '-',
1194                     entry->mas7_3 & MAS3_SW ? 'W' : '-',
1195                     entry->mas7_3 & MAS3_SX ? 'X' : '-',
1196                     entry->mas7_3 & MAS3_UR ? 'R' : '-',
1197                     entry->mas7_3 & MAS3_UW ? 'W' : '-',
1198                     entry->mas7_3 & MAS3_UX ? 'X' : '-',
1199                     entry->mas2 & MAS2_W ? 'W' : '-',
1200                     entry->mas2 & MAS2_I ? 'I' : '-',
1201                     entry->mas2 & MAS2_M ? 'M' : '-',
1202                     entry->mas2 & MAS2_G ? 'G' : '-',
1203                     entry->mas2 & MAS2_E ? 'E' : '-',
1204                     entry->mas7_3 & MAS3_U0 ? '0' : '-',
1205                     entry->mas7_3 & MAS3_U1 ? '1' : '-',
1206                     entry->mas7_3 & MAS3_U2 ? '2' : '-',
1207                     entry->mas7_3 & MAS3_U3 ? '3' : '-');
1208     }
1209 }
1210 
1211 static void mmubooke206_dump_mmu(CPUPPCState *env)
1212 {
1213     int offset = 0;
1214     int i;
1215 
1216     if (kvm_enabled() && !env->kvm_sw_tlb) {
1217         qemu_printf("Cannot access KVM TLB\n");
1218         return;
1219     }
1220 
1221     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1222         int size = booke206_tlb_size(env, i);
1223 
1224         if (size == 0) {
1225             continue;
1226         }
1227 
1228         mmubooke206_dump_one_tlb(env, i, offset, size);
1229         offset += size;
1230     }
1231 }
1232 
1233 static void mmu6xx_dump_BATs(CPUPPCState *env, int type)
1234 {
1235     target_ulong *BATlt, *BATut, *BATu, *BATl;
1236     target_ulong BEPIl, BEPIu, bl;
1237     int i;
1238 
1239     switch (type) {
1240     case ACCESS_CODE:
1241         BATlt = env->IBAT[1];
1242         BATut = env->IBAT[0];
1243         break;
1244     default:
1245         BATlt = env->DBAT[1];
1246         BATut = env->DBAT[0];
1247         break;
1248     }
1249 
1250     for (i = 0; i < env->nb_BATs; i++) {
1251         BATu = &BATut[i];
1252         BATl = &BATlt[i];
1253         BEPIu = *BATu & 0xF0000000;
1254         BEPIl = *BATu & 0x0FFE0000;
1255         bl = (*BATu & 0x00001FFC) << 15;
1256         qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
1257                     " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
1258                     TARGET_FMT_lx " " TARGET_FMT_lx "\n",
1259                     type == ACCESS_CODE ? "code" : "data", i,
1260                     *BATu, *BATl, BEPIu, BEPIl, bl);
1261     }
1262 }
1263 
1264 static void mmu6xx_dump_mmu(CPUPPCState *env)
1265 {
1266     PowerPCCPU *cpu = ppc_env_get_cpu(env);
1267     ppc6xx_tlb_t *tlb;
1268     target_ulong sr;
1269     int type, way, entry, i;
1270 
1271     qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu));
1272     qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu));
1273 
1274     qemu_printf("\nSegment registers:\n");
1275     for (i = 0; i < 32; i++) {
1276         sr = env->sr[i];
1277         if (sr & 0x80000000) {
1278             qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1279                         "CNTLR_SPEC=0x%05x\n", i,
1280                         sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
1281                         sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF),
1282                         (uint32_t)(sr & 0xFFFFF));
1283         } else {
1284             qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i,
1285                         sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
1286                         sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0,
1287                         (uint32_t)(sr & 0x00FFFFFF));
1288         }
1289     }
1290 
1291     qemu_printf("\nBATs:\n");
1292     mmu6xx_dump_BATs(env, ACCESS_INT);
1293     mmu6xx_dump_BATs(env, ACCESS_CODE);
1294 
1295     if (env->id_tlbs != 1) {
1296         qemu_printf("ERROR: 6xx MMU should have separated TLB"
1297                     " for code and data\n");
1298     }
1299 
1300     qemu_printf("\nTLBs                       [EPN    EPN + SIZE]\n");
1301 
1302     for (type = 0; type < 2; type++) {
1303         for (way = 0; way < env->nb_ways; way++) {
1304             for (entry = env->nb_tlb * type + env->tlb_per_way * way;
1305                  entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1));
1306                  entry++) {
1307 
1308                 tlb = &env->tlb.tlb6[entry];
1309                 qemu_printf("%s TLB %02d/%02d way:%d %s ["
1310                             TARGET_FMT_lx " " TARGET_FMT_lx "]\n",
1311                             type ? "code" : "data", entry % env->nb_tlb,
1312                             env->nb_tlb, way,
1313                             pte_is_valid(tlb->pte0) ? "valid" : "inval",
1314                             tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE);
1315             }
1316         }
1317     }
1318 }
1319 
1320 void dump_mmu(CPUPPCState *env)
1321 {
1322     switch (env->mmu_model) {
1323     case POWERPC_MMU_BOOKE:
1324         mmubooke_dump_mmu(env);
1325         break;
1326     case POWERPC_MMU_BOOKE206:
1327         mmubooke206_dump_mmu(env);
1328         break;
1329     case POWERPC_MMU_SOFT_6xx:
1330     case POWERPC_MMU_SOFT_74xx:
1331         mmu6xx_dump_mmu(env);
1332         break;
1333 #if defined(TARGET_PPC64)
1334     case POWERPC_MMU_64B:
1335     case POWERPC_MMU_2_03:
1336     case POWERPC_MMU_2_06:
1337     case POWERPC_MMU_2_07:
1338         dump_slb(ppc_env_get_cpu(env));
1339         break;
1340     case POWERPC_MMU_3_00:
1341         if (ppc64_v3_radix(ppc_env_get_cpu(env))) {
1342             /* TODO - Unsupported */
1343         } else {
1344             dump_slb(ppc_env_get_cpu(env));
1345             break;
1346         }
1347 #endif
1348     default:
1349         qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
1350     }
1351 }
1352 
1353 static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
1354                                  target_ulong eaddr, int rw)
1355 {
1356     int in_plb, ret;
1357 
1358     ctx->raddr = eaddr;
1359     ctx->prot = PAGE_READ | PAGE_EXEC;
1360     ret = 0;
1361     switch (env->mmu_model) {
1362     case POWERPC_MMU_SOFT_6xx:
1363     case POWERPC_MMU_SOFT_74xx:
1364     case POWERPC_MMU_SOFT_4xx:
1365     case POWERPC_MMU_REAL:
1366     case POWERPC_MMU_BOOKE:
1367         ctx->prot |= PAGE_WRITE;
1368         break;
1369 
1370     case POWERPC_MMU_SOFT_4xx_Z:
1371         if (unlikely(msr_pe != 0)) {
1372             /* 403 family add some particular protections,
1373              * using PBL/PBU registers for accesses with no translation.
1374              */
1375             in_plb =
1376                 /* Check PLB validity */
1377                 (env->pb[0] < env->pb[1] &&
1378                  /* and address in plb area */
1379                  eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1380                 (env->pb[2] < env->pb[3] &&
1381                  eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1382             if (in_plb ^ msr_px) {
1383                 /* Access in protected area */
1384                 if (rw == 1) {
1385                     /* Access is not allowed */
1386                     ret = -2;
1387                 }
1388             } else {
1389                 /* Read-write access is allowed */
1390                 ctx->prot |= PAGE_WRITE;
1391             }
1392         }
1393         break;
1394 
1395     default:
1396         /* Caller's checks mean we should never get here for other models */
1397         abort();
1398         return -1;
1399     }
1400 
1401     return ret;
1402 }
1403 
1404 static int get_physical_address_wtlb(
1405     CPUPPCState *env, mmu_ctx_t *ctx,
1406     target_ulong eaddr, int rw, int access_type,
1407     int mmu_idx)
1408 {
1409     PowerPCCPU *cpu = ppc_env_get_cpu(env);
1410     int ret = -1;
1411     bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
1412         || (access_type != ACCESS_CODE && msr_dr == 0);
1413 
1414     switch (env->mmu_model) {
1415     case POWERPC_MMU_SOFT_6xx:
1416     case POWERPC_MMU_SOFT_74xx:
1417         if (real_mode) {
1418             ret = check_physical(env, ctx, eaddr, rw);
1419         } else {
1420             /* Try to find a BAT */
1421             if (env->nb_BATs != 0) {
1422                 ret = get_bat_6xx_tlb(env, ctx, eaddr, rw, access_type);
1423             }
1424             if (ret < 0) {
1425                 /* We didn't match any BAT entry or don't have BATs */
1426                 ret = get_segment_6xx_tlb(env, ctx, eaddr, rw, access_type);
1427             }
1428         }
1429         break;
1430 
1431     case POWERPC_MMU_SOFT_4xx:
1432     case POWERPC_MMU_SOFT_4xx_Z:
1433         if (real_mode) {
1434             ret = check_physical(env, ctx, eaddr, rw);
1435         } else {
1436             ret = mmu40x_get_physical_address(env, ctx, eaddr,
1437                                               rw, access_type);
1438         }
1439         break;
1440     case POWERPC_MMU_BOOKE:
1441         ret = mmubooke_get_physical_address(env, ctx, eaddr,
1442                                             rw, access_type);
1443         break;
1444     case POWERPC_MMU_BOOKE206:
1445         ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1446                                                access_type, mmu_idx);
1447         break;
1448     case POWERPC_MMU_MPC8xx:
1449         /* XXX: TODO */
1450         cpu_abort(CPU(cpu), "MPC8xx MMU model is not implemented\n");
1451         break;
1452     case POWERPC_MMU_REAL:
1453         if (real_mode) {
1454             ret = check_physical(env, ctx, eaddr, rw);
1455         } else {
1456             cpu_abort(CPU(cpu), "PowerPC in real mode do not do any translation\n");
1457         }
1458         return -1;
1459     default:
1460         cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n");
1461         return -1;
1462     }
1463 
1464     return ret;
1465 }
1466 
1467 static int get_physical_address(
1468     CPUPPCState *env, mmu_ctx_t *ctx,
1469     target_ulong eaddr, int rw, int access_type)
1470 {
1471     return get_physical_address_wtlb(env, ctx, eaddr, rw, access_type, 0);
1472 }
1473 
1474 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
1475 {
1476     PowerPCCPU *cpu = POWERPC_CPU(cs);
1477     CPUPPCState *env = &cpu->env;
1478     mmu_ctx_t ctx;
1479 
1480     switch (env->mmu_model) {
1481 #if defined(TARGET_PPC64)
1482     case POWERPC_MMU_64B:
1483     case POWERPC_MMU_2_03:
1484     case POWERPC_MMU_2_06:
1485     case POWERPC_MMU_2_07:
1486         return ppc_hash64_get_phys_page_debug(cpu, addr);
1487     case POWERPC_MMU_3_00:
1488         return ppc64_v3_get_phys_page_debug(cpu, addr);
1489 #endif
1490 
1491     case POWERPC_MMU_32B:
1492     case POWERPC_MMU_601:
1493         return ppc_hash32_get_phys_page_debug(cpu, addr);
1494 
1495     default:
1496         ;
1497     }
1498 
1499     if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0)) {
1500 
1501         /* Some MMUs have separate TLBs for code and data. If we only try an
1502          * ACCESS_INT, we may not be able to read instructions mapped by code
1503          * TLBs, so we also try a ACCESS_CODE.
1504          */
1505         if (unlikely(get_physical_address(env, &ctx, addr, 0,
1506                                           ACCESS_CODE) != 0)) {
1507             return -1;
1508         }
1509     }
1510 
1511     return ctx.raddr & TARGET_PAGE_MASK;
1512 }
1513 
1514 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
1515                                      int rw, int mmu_idx)
1516 {
1517     uint32_t epid;
1518     bool as, pr;
1519     uint32_t missed_tid = 0;
1520     bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
1521     if (rw == 2) {
1522         as = msr_ir;
1523     }
1524     env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1525     env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1526     env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1527     env->spr[SPR_BOOKE_MAS3] = 0;
1528     env->spr[SPR_BOOKE_MAS6] = 0;
1529     env->spr[SPR_BOOKE_MAS7] = 0;
1530 
1531     /* AS */
1532     if (as) {
1533         env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1534         env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1535     }
1536 
1537     env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1538     env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1539 
1540     if (!use_epid) {
1541         switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1542         case MAS4_TIDSELD_PID0:
1543             missed_tid = env->spr[SPR_BOOKE_PID];
1544             break;
1545         case MAS4_TIDSELD_PID1:
1546             missed_tid = env->spr[SPR_BOOKE_PID1];
1547             break;
1548         case MAS4_TIDSELD_PID2:
1549             missed_tid = env->spr[SPR_BOOKE_PID2];
1550             break;
1551         }
1552         env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1553     } else {
1554         missed_tid = epid;
1555         env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
1556     }
1557     env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
1558 
1559 
1560     /* next victim logic */
1561     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1562     env->last_way++;
1563     env->last_way &= booke206_tlb_ways(env, 0) - 1;
1564     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1565 }
1566 
1567 /* Perform address translation */
1568 static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
1569                                     int rw, int mmu_idx)
1570 {
1571     CPUState *cs = CPU(ppc_env_get_cpu(env));
1572     PowerPCCPU *cpu = POWERPC_CPU(cs);
1573     mmu_ctx_t ctx;
1574     int access_type;
1575     int ret = 0;
1576 
1577     if (rw == 2) {
1578         /* code access */
1579         rw = 0;
1580         access_type = ACCESS_CODE;
1581     } else {
1582         /* data access */
1583         access_type = env->access_type;
1584     }
1585     ret = get_physical_address_wtlb(env, &ctx, address, rw,
1586                                     access_type, mmu_idx);
1587     if (ret == 0) {
1588         tlb_set_page(cs, address & TARGET_PAGE_MASK,
1589                      ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1590                      mmu_idx, TARGET_PAGE_SIZE);
1591         ret = 0;
1592     } else if (ret < 0) {
1593         LOG_MMU_STATE(cs);
1594         if (access_type == ACCESS_CODE) {
1595             switch (ret) {
1596             case -1:
1597                 /* No matches in page tables or TLB */
1598                 switch (env->mmu_model) {
1599                 case POWERPC_MMU_SOFT_6xx:
1600                     cs->exception_index = POWERPC_EXCP_IFTLB;
1601                     env->error_code = 1 << 18;
1602                     env->spr[SPR_IMISS] = address;
1603                     env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1604                     goto tlb_miss;
1605                 case POWERPC_MMU_SOFT_74xx:
1606                     cs->exception_index = POWERPC_EXCP_IFTLB;
1607                     goto tlb_miss_74xx;
1608                 case POWERPC_MMU_SOFT_4xx:
1609                 case POWERPC_MMU_SOFT_4xx_Z:
1610                     cs->exception_index = POWERPC_EXCP_ITLB;
1611                     env->error_code = 0;
1612                     env->spr[SPR_40x_DEAR] = address;
1613                     env->spr[SPR_40x_ESR] = 0x00000000;
1614                     break;
1615                 case POWERPC_MMU_BOOKE206:
1616                     booke206_update_mas_tlb_miss(env, address, 2, mmu_idx);
1617                     /* fall through */
1618                 case POWERPC_MMU_BOOKE:
1619                     cs->exception_index = POWERPC_EXCP_ITLB;
1620                     env->error_code = 0;
1621                     env->spr[SPR_BOOKE_DEAR] = address;
1622                     env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 0);
1623                     return -1;
1624                 case POWERPC_MMU_MPC8xx:
1625                     /* XXX: TODO */
1626                     cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
1627                     break;
1628                 case POWERPC_MMU_REAL:
1629                     cpu_abort(cs, "PowerPC in real mode should never raise "
1630                               "any MMU exceptions\n");
1631                     return -1;
1632                 default:
1633                     cpu_abort(cs, "Unknown or invalid MMU model\n");
1634                     return -1;
1635                 }
1636                 break;
1637             case -2:
1638                 /* Access rights violation */
1639                 cs->exception_index = POWERPC_EXCP_ISI;
1640                 env->error_code = 0x08000000;
1641                 break;
1642             case -3:
1643                 /* No execute protection violation */
1644                 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1645                     (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1646                     env->spr[SPR_BOOKE_ESR] = 0x00000000;
1647                 }
1648                 cs->exception_index = POWERPC_EXCP_ISI;
1649                 env->error_code = 0x10000000;
1650                 break;
1651             case -4:
1652                 /* Direct store exception */
1653                 /* No code fetch is allowed in direct-store areas */
1654                 cs->exception_index = POWERPC_EXCP_ISI;
1655                 env->error_code = 0x10000000;
1656                 break;
1657             }
1658         } else {
1659             switch (ret) {
1660             case -1:
1661                 /* No matches in page tables or TLB */
1662                 switch (env->mmu_model) {
1663                 case POWERPC_MMU_SOFT_6xx:
1664                     if (rw == 1) {
1665                         cs->exception_index = POWERPC_EXCP_DSTLB;
1666                         env->error_code = 1 << 16;
1667                     } else {
1668                         cs->exception_index = POWERPC_EXCP_DLTLB;
1669                         env->error_code = 0;
1670                     }
1671                     env->spr[SPR_DMISS] = address;
1672                     env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1673                 tlb_miss:
1674                     env->error_code |= ctx.key << 19;
1675                     env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
1676                         get_pteg_offset32(cpu, ctx.hash[0]);
1677                     env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
1678                         get_pteg_offset32(cpu, ctx.hash[1]);
1679                     break;
1680                 case POWERPC_MMU_SOFT_74xx:
1681                     if (rw == 1) {
1682                         cs->exception_index = POWERPC_EXCP_DSTLB;
1683                     } else {
1684                         cs->exception_index = POWERPC_EXCP_DLTLB;
1685                     }
1686                 tlb_miss_74xx:
1687                     /* Implement LRU algorithm */
1688                     env->error_code = ctx.key << 19;
1689                     env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1690                         ((env->last_way + 1) & (env->nb_ways - 1));
1691                     env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1692                     break;
1693                 case POWERPC_MMU_SOFT_4xx:
1694                 case POWERPC_MMU_SOFT_4xx_Z:
1695                     cs->exception_index = POWERPC_EXCP_DTLB;
1696                     env->error_code = 0;
1697                     env->spr[SPR_40x_DEAR] = address;
1698                     if (rw) {
1699                         env->spr[SPR_40x_ESR] = 0x00800000;
1700                     } else {
1701                         env->spr[SPR_40x_ESR] = 0x00000000;
1702                     }
1703                     break;
1704                 case POWERPC_MMU_MPC8xx:
1705                     /* XXX: TODO */
1706                     cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
1707                     break;
1708                 case POWERPC_MMU_BOOKE206:
1709                     booke206_update_mas_tlb_miss(env, address, rw, mmu_idx);
1710                     /* fall through */
1711                 case POWERPC_MMU_BOOKE:
1712                     cs->exception_index = POWERPC_EXCP_DTLB;
1713                     env->error_code = 0;
1714                     env->spr[SPR_BOOKE_DEAR] = address;
1715                     env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, rw);
1716                     return -1;
1717                 case POWERPC_MMU_REAL:
1718                     cpu_abort(cs, "PowerPC in real mode should never raise "
1719                               "any MMU exceptions\n");
1720                     return -1;
1721                 default:
1722                     cpu_abort(cs, "Unknown or invalid MMU model\n");
1723                     return -1;
1724                 }
1725                 break;
1726             case -2:
1727                 /* Access rights violation */
1728                 cs->exception_index = POWERPC_EXCP_DSI;
1729                 env->error_code = 0;
1730                 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1731                     || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1732                     env->spr[SPR_40x_DEAR] = address;
1733                     if (rw) {
1734                         env->spr[SPR_40x_ESR] |= 0x00800000;
1735                     }
1736                 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1737                            (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1738                     env->spr[SPR_BOOKE_DEAR] = address;
1739                     env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, rw);
1740                 } else {
1741                     env->spr[SPR_DAR] = address;
1742                     if (rw == 1) {
1743                         env->spr[SPR_DSISR] = 0x0A000000;
1744                     } else {
1745                         env->spr[SPR_DSISR] = 0x08000000;
1746                     }
1747                 }
1748                 break;
1749             case -4:
1750                 /* Direct store exception */
1751                 switch (access_type) {
1752                 case ACCESS_FLOAT:
1753                     /* Floating point load/store */
1754                     cs->exception_index = POWERPC_EXCP_ALIGN;
1755                     env->error_code = POWERPC_EXCP_ALIGN_FP;
1756                     env->spr[SPR_DAR] = address;
1757                     break;
1758                 case ACCESS_RES:
1759                     /* lwarx, ldarx or stwcx. */
1760                     cs->exception_index = POWERPC_EXCP_DSI;
1761                     env->error_code = 0;
1762                     env->spr[SPR_DAR] = address;
1763                     if (rw == 1) {
1764                         env->spr[SPR_DSISR] = 0x06000000;
1765                     } else {
1766                         env->spr[SPR_DSISR] = 0x04000000;
1767                     }
1768                     break;
1769                 case ACCESS_EXT:
1770                     /* eciwx or ecowx */
1771                     cs->exception_index = POWERPC_EXCP_DSI;
1772                     env->error_code = 0;
1773                     env->spr[SPR_DAR] = address;
1774                     if (rw == 1) {
1775                         env->spr[SPR_DSISR] = 0x06100000;
1776                     } else {
1777                         env->spr[SPR_DSISR] = 0x04100000;
1778                     }
1779                     break;
1780                 default:
1781                     printf("DSI: invalid exception (%d)\n", ret);
1782                     cs->exception_index = POWERPC_EXCP_PROGRAM;
1783                     env->error_code =
1784                         POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1785                     env->spr[SPR_DAR] = address;
1786                     break;
1787                 }
1788                 break;
1789             }
1790         }
1791         ret = 1;
1792     }
1793 
1794     return ret;
1795 }
1796 
1797 /*****************************************************************************/
1798 /* BATs management */
1799 #if !defined(FLUSH_ALL_TLBS)
1800 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1801                                      target_ulong mask)
1802 {
1803     CPUState *cs = CPU(ppc_env_get_cpu(env));
1804     target_ulong base, end, page;
1805 
1806     base = BATu & ~0x0001FFFF;
1807     end = base + mask + 0x00020000;
1808     LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1809              TARGET_FMT_lx ")\n", base, end, mask);
1810     for (page = base; page != end; page += TARGET_PAGE_SIZE) {
1811         tlb_flush_page(cs, page);
1812     }
1813     LOG_BATS("Flush done\n");
1814 }
1815 #endif
1816 
1817 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1818                                   target_ulong value)
1819 {
1820     LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1821              nr, ul == 0 ? 'u' : 'l', value, env->nip);
1822 }
1823 
1824 void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1825 {
1826     target_ulong mask;
1827 #if defined(FLUSH_ALL_TLBS)
1828     PowerPCCPU *cpu = ppc_env_get_cpu(env);
1829 #endif
1830 
1831     dump_store_bat(env, 'I', 0, nr, value);
1832     if (env->IBAT[0][nr] != value) {
1833         mask = (value << 15) & 0x0FFE0000UL;
1834 #if !defined(FLUSH_ALL_TLBS)
1835         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1836 #endif
1837         /* When storing valid upper BAT, mask BEPI and BRPN
1838          * and invalidate all TLBs covered by this BAT
1839          */
1840         mask = (value << 15) & 0x0FFE0000UL;
1841         env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1842             (value & ~0x0001FFFFUL & ~mask);
1843         env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1844             (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1845 #if !defined(FLUSH_ALL_TLBS)
1846         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1847 #else
1848         tlb_flush(CPU(cpu));
1849 #endif
1850     }
1851 }
1852 
1853 void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1854 {
1855     dump_store_bat(env, 'I', 1, nr, value);
1856     env->IBAT[1][nr] = value;
1857 }
1858 
1859 void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1860 {
1861     target_ulong mask;
1862 #if defined(FLUSH_ALL_TLBS)
1863     PowerPCCPU *cpu = ppc_env_get_cpu(env);
1864 #endif
1865 
1866     dump_store_bat(env, 'D', 0, nr, value);
1867     if (env->DBAT[0][nr] != value) {
1868         /* When storing valid upper BAT, mask BEPI and BRPN
1869          * and invalidate all TLBs covered by this BAT
1870          */
1871         mask = (value << 15) & 0x0FFE0000UL;
1872 #if !defined(FLUSH_ALL_TLBS)
1873         do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1874 #endif
1875         mask = (value << 15) & 0x0FFE0000UL;
1876         env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1877             (value & ~0x0001FFFFUL & ~mask);
1878         env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1879             (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1880 #if !defined(FLUSH_ALL_TLBS)
1881         do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1882 #else
1883         tlb_flush(CPU(cpu));
1884 #endif
1885     }
1886 }
1887 
1888 void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1889 {
1890     dump_store_bat(env, 'D', 1, nr, value);
1891     env->DBAT[1][nr] = value;
1892 }
1893 
1894 void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
1895 {
1896     target_ulong mask;
1897 #if defined(FLUSH_ALL_TLBS)
1898     PowerPCCPU *cpu = ppc_env_get_cpu(env);
1899     int do_inval;
1900 #endif
1901 
1902     dump_store_bat(env, 'I', 0, nr, value);
1903     if (env->IBAT[0][nr] != value) {
1904 #if defined(FLUSH_ALL_TLBS)
1905         do_inval = 0;
1906 #endif
1907         mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1908         if (env->IBAT[1][nr] & 0x40) {
1909             /* Invalidate BAT only if it is valid */
1910 #if !defined(FLUSH_ALL_TLBS)
1911             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1912 #else
1913             do_inval = 1;
1914 #endif
1915         }
1916         /* When storing valid upper BAT, mask BEPI and BRPN
1917          * and invalidate all TLBs covered by this BAT
1918          */
1919         env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1920             (value & ~0x0001FFFFUL & ~mask);
1921         env->DBAT[0][nr] = env->IBAT[0][nr];
1922         if (env->IBAT[1][nr] & 0x40) {
1923 #if !defined(FLUSH_ALL_TLBS)
1924             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1925 #else
1926             do_inval = 1;
1927 #endif
1928         }
1929 #if defined(FLUSH_ALL_TLBS)
1930         if (do_inval) {
1931             tlb_flush(CPU(cpu));
1932         }
1933 #endif
1934     }
1935 }
1936 
1937 void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
1938 {
1939 #if !defined(FLUSH_ALL_TLBS)
1940     target_ulong mask;
1941 #else
1942     PowerPCCPU *cpu = ppc_env_get_cpu(env);
1943     int do_inval;
1944 #endif
1945 
1946     dump_store_bat(env, 'I', 1, nr, value);
1947     if (env->IBAT[1][nr] != value) {
1948 #if defined(FLUSH_ALL_TLBS)
1949         do_inval = 0;
1950 #endif
1951         if (env->IBAT[1][nr] & 0x40) {
1952 #if !defined(FLUSH_ALL_TLBS)
1953             mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1954             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1955 #else
1956             do_inval = 1;
1957 #endif
1958         }
1959         if (value & 0x40) {
1960 #if !defined(FLUSH_ALL_TLBS)
1961             mask = (value << 17) & 0x0FFE0000UL;
1962             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1963 #else
1964             do_inval = 1;
1965 #endif
1966         }
1967         env->IBAT[1][nr] = value;
1968         env->DBAT[1][nr] = value;
1969 #if defined(FLUSH_ALL_TLBS)
1970         if (do_inval) {
1971             tlb_flush(CPU(cpu));
1972         }
1973 #endif
1974     }
1975 }
1976 
1977 /*****************************************************************************/
1978 /* TLB management */
1979 void ppc_tlb_invalidate_all(CPUPPCState *env)
1980 {
1981     PowerPCCPU *cpu = ppc_env_get_cpu(env);
1982 
1983 #if defined(TARGET_PPC64)
1984     if (env->mmu_model & POWERPC_MMU_64) {
1985         env->tlb_need_flush = 0;
1986         tlb_flush(CPU(cpu));
1987     } else
1988 #endif /* defined(TARGET_PPC64) */
1989     switch (env->mmu_model) {
1990     case POWERPC_MMU_SOFT_6xx:
1991     case POWERPC_MMU_SOFT_74xx:
1992         ppc6xx_tlb_invalidate_all(env);
1993         break;
1994     case POWERPC_MMU_SOFT_4xx:
1995     case POWERPC_MMU_SOFT_4xx_Z:
1996         ppc4xx_tlb_invalidate_all(env);
1997         break;
1998     case POWERPC_MMU_REAL:
1999         cpu_abort(CPU(cpu), "No TLB for PowerPC 4xx in real mode\n");
2000         break;
2001     case POWERPC_MMU_MPC8xx:
2002         /* XXX: TODO */
2003         cpu_abort(CPU(cpu), "MPC8xx MMU model is not implemented\n");
2004         break;
2005     case POWERPC_MMU_BOOKE:
2006         tlb_flush(CPU(cpu));
2007         break;
2008     case POWERPC_MMU_BOOKE206:
2009         booke206_flush_tlb(env, -1, 0);
2010         break;
2011     case POWERPC_MMU_32B:
2012     case POWERPC_MMU_601:
2013         env->tlb_need_flush = 0;
2014         tlb_flush(CPU(cpu));
2015         break;
2016     default:
2017         /* XXX: TODO */
2018         cpu_abort(CPU(cpu), "Unknown MMU model %x\n", env->mmu_model);
2019         break;
2020     }
2021 }
2022 
2023 void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
2024 {
2025 #if !defined(FLUSH_ALL_TLBS)
2026     addr &= TARGET_PAGE_MASK;
2027 #if defined(TARGET_PPC64)
2028     if (env->mmu_model & POWERPC_MMU_64) {
2029         /* tlbie invalidate TLBs for all segments */
2030         /* XXX: given the fact that there are too many segments to invalidate,
2031          *      and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
2032          *      we just invalidate all TLBs
2033          */
2034         env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2035     } else
2036 #endif /* defined(TARGET_PPC64) */
2037     switch (env->mmu_model) {
2038     case POWERPC_MMU_SOFT_6xx:
2039     case POWERPC_MMU_SOFT_74xx:
2040         ppc6xx_tlb_invalidate_virt(env, addr, 0);
2041         if (env->id_tlbs == 1) {
2042             ppc6xx_tlb_invalidate_virt(env, addr, 1);
2043         }
2044         break;
2045     case POWERPC_MMU_32B:
2046     case POWERPC_MMU_601:
2047         /* Actual CPUs invalidate entire congruence classes based on the
2048          * geometry of their TLBs and some OSes take that into account,
2049          * we just mark the TLB to be flushed later (context synchronizing
2050          * event or sync instruction on 32-bit).
2051          */
2052         env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2053         break;
2054     default:
2055         /* Should never reach here with other MMU models */
2056         assert(0);
2057     }
2058 #else
2059     ppc_tlb_invalidate_all(env);
2060 #endif
2061 }
2062 
2063 /*****************************************************************************/
2064 /* Special registers manipulation */
2065 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
2066 {
2067     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2068     qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
2069     assert(!cpu->vhyp);
2070 #if defined(TARGET_PPC64)
2071     if (env->mmu_model & POWERPC_MMU_64) {
2072         target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
2073         target_ulong htabsize = value & SDR_64_HTABSIZE;
2074 
2075         if (value & ~sdr_mask) {
2076             error_report("Invalid bits 0x"TARGET_FMT_lx" set in SDR1",
2077                          value & ~sdr_mask);
2078             value &= sdr_mask;
2079         }
2080         if (htabsize > 28) {
2081             error_report("Invalid HTABSIZE 0x" TARGET_FMT_lx" stored in SDR1",
2082                          htabsize);
2083             return;
2084         }
2085     }
2086 #endif /* defined(TARGET_PPC64) */
2087     /* FIXME: Should check for valid HTABMASK values in 32-bit case */
2088     env->spr[SPR_SDR1] = value;
2089 }
2090 
2091 #if defined(TARGET_PPC64)
2092 void ppc_store_ptcr(CPUPPCState *env, target_ulong value)
2093 {
2094     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2095     target_ulong ptcr_mask = PTCR_PATB | PTCR_PATS;
2096     target_ulong patbsize = value & PTCR_PATS;
2097 
2098     qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
2099 
2100     assert(!cpu->vhyp);
2101     assert(env->mmu_model & POWERPC_MMU_3_00);
2102 
2103     if (value & ~ptcr_mask) {
2104         error_report("Invalid bits 0x"TARGET_FMT_lx" set in PTCR",
2105                      value & ~ptcr_mask);
2106         value &= ptcr_mask;
2107     }
2108 
2109     if (patbsize > 24) {
2110         error_report("Invalid Partition Table size 0x" TARGET_FMT_lx
2111                      " stored in PTCR", patbsize);
2112         return;
2113     }
2114 
2115     env->spr[SPR_PTCR] = value;
2116 }
2117 
2118 #endif /* defined(TARGET_PPC64) */
2119 
2120 /* Segment registers load and store */
2121 target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
2122 {
2123 #if defined(TARGET_PPC64)
2124     if (env->mmu_model & POWERPC_MMU_64) {
2125         /* XXX */
2126         return 0;
2127     }
2128 #endif
2129     return env->sr[sr_num];
2130 }
2131 
2132 void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
2133 {
2134     qemu_log_mask(CPU_LOG_MMU,
2135             "%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2136             (int)srnum, value, env->sr[srnum]);
2137 #if defined(TARGET_PPC64)
2138     if (env->mmu_model & POWERPC_MMU_64) {
2139         PowerPCCPU *cpu = ppc_env_get_cpu(env);
2140         uint64_t esid, vsid;
2141 
2142         /* ESID = srnum */
2143         esid = ((uint64_t)(srnum & 0xf) << 28) | SLB_ESID_V;
2144 
2145         /* VSID = VSID */
2146         vsid = (value & 0xfffffff) << 12;
2147         /* flags = flags */
2148         vsid |= ((value >> 27) & 0xf) << 8;
2149 
2150         ppc_store_slb(cpu, srnum, esid, vsid);
2151     } else
2152 #endif
2153     if (env->sr[srnum] != value) {
2154         env->sr[srnum] = value;
2155 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2156    flusing the whole TLB. */
2157 #if !defined(FLUSH_ALL_TLBS) && 0
2158         {
2159             target_ulong page, end;
2160             /* Invalidate 256 MB of virtual memory */
2161             page = (16 << 20) * srnum;
2162             end = page + (16 << 20);
2163             for (; page != end; page += TARGET_PAGE_SIZE) {
2164                 tlb_flush_page(CPU(cpu), page);
2165             }
2166         }
2167 #else
2168         env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2169 #endif
2170     }
2171 }
2172 
2173 /* TLB management */
2174 void helper_tlbia(CPUPPCState *env)
2175 {
2176     ppc_tlb_invalidate_all(env);
2177 }
2178 
2179 void helper_tlbie(CPUPPCState *env, target_ulong addr)
2180 {
2181     ppc_tlb_invalidate_one(env, addr);
2182 }
2183 
2184 void helper_tlbiva(CPUPPCState *env, target_ulong addr)
2185 {
2186     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2187 
2188     /* tlbiva instruction only exists on BookE */
2189     assert(env->mmu_model == POWERPC_MMU_BOOKE);
2190     /* XXX: TODO */
2191     cpu_abort(CPU(cpu), "BookE MMU model is not implemented\n");
2192 }
2193 
2194 /* Software driven TLBs management */
2195 /* PowerPC 602/603 software TLB load instructions helpers */
2196 static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2197 {
2198     target_ulong RPN, CMP, EPN;
2199     int way;
2200 
2201     RPN = env->spr[SPR_RPA];
2202     if (is_code) {
2203         CMP = env->spr[SPR_ICMP];
2204         EPN = env->spr[SPR_IMISS];
2205     } else {
2206         CMP = env->spr[SPR_DCMP];
2207         EPN = env->spr[SPR_DMISS];
2208     }
2209     way = (env->spr[SPR_SRR1] >> 17) & 1;
2210     (void)EPN; /* avoid a compiler warning */
2211     LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2212               " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2213               RPN, way);
2214     /* Store this TLB */
2215     ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2216                      way, is_code, CMP, RPN);
2217 }
2218 
2219 void helper_6xx_tlbd(CPUPPCState *env, target_ulong EPN)
2220 {
2221     do_6xx_tlb(env, EPN, 0);
2222 }
2223 
2224 void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
2225 {
2226     do_6xx_tlb(env, EPN, 1);
2227 }
2228 
2229 /* PowerPC 74xx software TLB load instructions helpers */
2230 static void do_74xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2231 {
2232     target_ulong RPN, CMP, EPN;
2233     int way;
2234 
2235     RPN = env->spr[SPR_PTELO];
2236     CMP = env->spr[SPR_PTEHI];
2237     EPN = env->spr[SPR_TLBMISS] & ~0x3;
2238     way = env->spr[SPR_TLBMISS] & 0x3;
2239     (void)EPN; /* avoid a compiler warning */
2240     LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2241               " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2242               RPN, way);
2243     /* Store this TLB */
2244     ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2245                      way, is_code, CMP, RPN);
2246 }
2247 
2248 void helper_74xx_tlbd(CPUPPCState *env, target_ulong EPN)
2249 {
2250     do_74xx_tlb(env, EPN, 0);
2251 }
2252 
2253 void helper_74xx_tlbi(CPUPPCState *env, target_ulong EPN)
2254 {
2255     do_74xx_tlb(env, EPN, 1);
2256 }
2257 
2258 /*****************************************************************************/
2259 /* PowerPC 601 specific instructions (POWER bridge) */
2260 
2261 target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
2262 {
2263     mmu_ctx_t ctx;
2264     int nb_BATs;
2265     target_ulong ret = 0;
2266 
2267     /* We don't have to generate many instances of this instruction,
2268      * as rac is supervisor only.
2269      */
2270     /* XXX: FIX THIS: Pretend we have no BAT */
2271     nb_BATs = env->nb_BATs;
2272     env->nb_BATs = 0;
2273     if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) {
2274         ret = ctx.raddr;
2275     }
2276     env->nb_BATs = nb_BATs;
2277     return ret;
2278 }
2279 
2280 static inline target_ulong booke_tlb_to_page_size(int size)
2281 {
2282     return 1024 << (2 * size);
2283 }
2284 
2285 static inline int booke_page_size_to_tlb(target_ulong page_size)
2286 {
2287     int size;
2288 
2289     switch (page_size) {
2290     case 0x00000400UL:
2291         size = 0x0;
2292         break;
2293     case 0x00001000UL:
2294         size = 0x1;
2295         break;
2296     case 0x00004000UL:
2297         size = 0x2;
2298         break;
2299     case 0x00010000UL:
2300         size = 0x3;
2301         break;
2302     case 0x00040000UL:
2303         size = 0x4;
2304         break;
2305     case 0x00100000UL:
2306         size = 0x5;
2307         break;
2308     case 0x00400000UL:
2309         size = 0x6;
2310         break;
2311     case 0x01000000UL:
2312         size = 0x7;
2313         break;
2314     case 0x04000000UL:
2315         size = 0x8;
2316         break;
2317     case 0x10000000UL:
2318         size = 0x9;
2319         break;
2320     case 0x40000000UL:
2321         size = 0xA;
2322         break;
2323 #if defined(TARGET_PPC64)
2324     case 0x000100000000ULL:
2325         size = 0xB;
2326         break;
2327     case 0x000400000000ULL:
2328         size = 0xC;
2329         break;
2330     case 0x001000000000ULL:
2331         size = 0xD;
2332         break;
2333     case 0x004000000000ULL:
2334         size = 0xE;
2335         break;
2336     case 0x010000000000ULL:
2337         size = 0xF;
2338         break;
2339 #endif
2340     default:
2341         size = -1;
2342         break;
2343     }
2344 
2345     return size;
2346 }
2347 
2348 /* Helpers for 4xx TLB management */
2349 #define PPC4XX_TLB_ENTRY_MASK       0x0000003f  /* Mask for 64 TLB entries */
2350 
2351 #define PPC4XX_TLBHI_V              0x00000040
2352 #define PPC4XX_TLBHI_E              0x00000020
2353 #define PPC4XX_TLBHI_SIZE_MIN       0
2354 #define PPC4XX_TLBHI_SIZE_MAX       7
2355 #define PPC4XX_TLBHI_SIZE_DEFAULT   1
2356 #define PPC4XX_TLBHI_SIZE_SHIFT     7
2357 #define PPC4XX_TLBHI_SIZE_MASK      0x00000007
2358 
2359 #define PPC4XX_TLBLO_EX             0x00000200
2360 #define PPC4XX_TLBLO_WR             0x00000100
2361 #define PPC4XX_TLBLO_ATTR_MASK      0x000000FF
2362 #define PPC4XX_TLBLO_RPN_MASK       0xFFFFFC00
2363 
2364 target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry)
2365 {
2366     ppcemb_tlb_t *tlb;
2367     target_ulong ret;
2368     int size;
2369 
2370     entry &= PPC4XX_TLB_ENTRY_MASK;
2371     tlb = &env->tlb.tlbe[entry];
2372     ret = tlb->EPN;
2373     if (tlb->prot & PAGE_VALID) {
2374         ret |= PPC4XX_TLBHI_V;
2375     }
2376     size = booke_page_size_to_tlb(tlb->size);
2377     if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) {
2378         size = PPC4XX_TLBHI_SIZE_DEFAULT;
2379     }
2380     ret |= size << PPC4XX_TLBHI_SIZE_SHIFT;
2381     env->spr[SPR_40x_PID] = tlb->PID;
2382     return ret;
2383 }
2384 
2385 target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, target_ulong entry)
2386 {
2387     ppcemb_tlb_t *tlb;
2388     target_ulong ret;
2389 
2390     entry &= PPC4XX_TLB_ENTRY_MASK;
2391     tlb = &env->tlb.tlbe[entry];
2392     ret = tlb->RPN;
2393     if (tlb->prot & PAGE_EXEC) {
2394         ret |= PPC4XX_TLBLO_EX;
2395     }
2396     if (tlb->prot & PAGE_WRITE) {
2397         ret |= PPC4XX_TLBLO_WR;
2398     }
2399     return ret;
2400 }
2401 
2402 void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
2403                          target_ulong val)
2404 {
2405     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2406     CPUState *cs = CPU(cpu);
2407     ppcemb_tlb_t *tlb;
2408     target_ulong page, end;
2409 
2410     LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
2411               val);
2412     entry &= PPC4XX_TLB_ENTRY_MASK;
2413     tlb = &env->tlb.tlbe[entry];
2414     /* Invalidate previous TLB (if it's valid) */
2415     if (tlb->prot & PAGE_VALID) {
2416         end = tlb->EPN + tlb->size;
2417         LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end "
2418                   TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2419         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2420             tlb_flush_page(cs, page);
2421         }
2422     }
2423     tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
2424                                        & PPC4XX_TLBHI_SIZE_MASK);
2425     /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2426      * If this ever occurs, we should implement TARGET_PAGE_BITS_VARY
2427      */
2428     if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
2429         cpu_abort(cs, "TLB size " TARGET_FMT_lu " < %u "
2430                   "are not supported (%d)\n"
2431                   "Please implement TARGET_PAGE_BITS_VARY\n",
2432                   tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
2433     }
2434     tlb->EPN = val & ~(tlb->size - 1);
2435     if (val & PPC4XX_TLBHI_V) {
2436         tlb->prot |= PAGE_VALID;
2437         if (val & PPC4XX_TLBHI_E) {
2438             /* XXX: TO BE FIXED */
2439             cpu_abort(cs,
2440                       "Little-endian TLB entries are not supported by now\n");
2441         }
2442     } else {
2443         tlb->prot &= ~PAGE_VALID;
2444     }
2445     tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2446     LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2447               " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2448               (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2449               tlb->prot & PAGE_READ ? 'r' : '-',
2450               tlb->prot & PAGE_WRITE ? 'w' : '-',
2451               tlb->prot & PAGE_EXEC ? 'x' : '-',
2452               tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2453     /* Invalidate new TLB (if valid) */
2454     if (tlb->prot & PAGE_VALID) {
2455         end = tlb->EPN + tlb->size;
2456         LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end "
2457                   TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2458         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2459             tlb_flush_page(cs, page);
2460         }
2461     }
2462 }
2463 
2464 void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry,
2465                          target_ulong val)
2466 {
2467     ppcemb_tlb_t *tlb;
2468 
2469     LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
2470               val);
2471     entry &= PPC4XX_TLB_ENTRY_MASK;
2472     tlb = &env->tlb.tlbe[entry];
2473     tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
2474     tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
2475     tlb->prot = PAGE_READ;
2476     if (val & PPC4XX_TLBLO_EX) {
2477         tlb->prot |= PAGE_EXEC;
2478     }
2479     if (val & PPC4XX_TLBLO_WR) {
2480         tlb->prot |= PAGE_WRITE;
2481     }
2482     LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2483               " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2484               (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2485               tlb->prot & PAGE_READ ? 'r' : '-',
2486               tlb->prot & PAGE_WRITE ? 'w' : '-',
2487               tlb->prot & PAGE_EXEC ? 'x' : '-',
2488               tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2489 }
2490 
2491 target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address)
2492 {
2493     return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
2494 }
2495 
2496 /* PowerPC 440 TLB management */
2497 void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry,
2498                       target_ulong value)
2499 {
2500     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2501     ppcemb_tlb_t *tlb;
2502     target_ulong EPN, RPN, size;
2503     int do_flush_tlbs;
2504 
2505     LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n",
2506               __func__, word, (int)entry, value);
2507     do_flush_tlbs = 0;
2508     entry &= 0x3F;
2509     tlb = &env->tlb.tlbe[entry];
2510     switch (word) {
2511     default:
2512         /* Just here to please gcc */
2513     case 0:
2514         EPN = value & 0xFFFFFC00;
2515         if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) {
2516             do_flush_tlbs = 1;
2517         }
2518         tlb->EPN = EPN;
2519         size = booke_tlb_to_page_size((value >> 4) & 0xF);
2520         if ((tlb->prot & PAGE_VALID) && tlb->size < size) {
2521             do_flush_tlbs = 1;
2522         }
2523         tlb->size = size;
2524         tlb->attr &= ~0x1;
2525         tlb->attr |= (value >> 8) & 1;
2526         if (value & 0x200) {
2527             tlb->prot |= PAGE_VALID;
2528         } else {
2529             if (tlb->prot & PAGE_VALID) {
2530                 tlb->prot &= ~PAGE_VALID;
2531                 do_flush_tlbs = 1;
2532             }
2533         }
2534         tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2535         if (do_flush_tlbs) {
2536             tlb_flush(CPU(cpu));
2537         }
2538         break;
2539     case 1:
2540         RPN = value & 0xFFFFFC0F;
2541         if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) {
2542             tlb_flush(CPU(cpu));
2543         }
2544         tlb->RPN = RPN;
2545         break;
2546     case 2:
2547         tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
2548         tlb->prot = tlb->prot & PAGE_VALID;
2549         if (value & 0x1) {
2550             tlb->prot |= PAGE_READ << 4;
2551         }
2552         if (value & 0x2) {
2553             tlb->prot |= PAGE_WRITE << 4;
2554         }
2555         if (value & 0x4) {
2556             tlb->prot |= PAGE_EXEC << 4;
2557         }
2558         if (value & 0x8) {
2559             tlb->prot |= PAGE_READ;
2560         }
2561         if (value & 0x10) {
2562             tlb->prot |= PAGE_WRITE;
2563         }
2564         if (value & 0x20) {
2565             tlb->prot |= PAGE_EXEC;
2566         }
2567         break;
2568     }
2569 }
2570 
2571 target_ulong helper_440_tlbre(CPUPPCState *env, uint32_t word,
2572                               target_ulong entry)
2573 {
2574     ppcemb_tlb_t *tlb;
2575     target_ulong ret;
2576     int size;
2577 
2578     entry &= 0x3F;
2579     tlb = &env->tlb.tlbe[entry];
2580     switch (word) {
2581     default:
2582         /* Just here to please gcc */
2583     case 0:
2584         ret = tlb->EPN;
2585         size = booke_page_size_to_tlb(tlb->size);
2586         if (size < 0 || size > 0xF) {
2587             size = 1;
2588         }
2589         ret |= size << 4;
2590         if (tlb->attr & 0x1) {
2591             ret |= 0x100;
2592         }
2593         if (tlb->prot & PAGE_VALID) {
2594             ret |= 0x200;
2595         }
2596         env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2597         env->spr[SPR_440_MMUCR] |= tlb->PID;
2598         break;
2599     case 1:
2600         ret = tlb->RPN;
2601         break;
2602     case 2:
2603         ret = tlb->attr & ~0x1;
2604         if (tlb->prot & (PAGE_READ << 4)) {
2605             ret |= 0x1;
2606         }
2607         if (tlb->prot & (PAGE_WRITE << 4)) {
2608             ret |= 0x2;
2609         }
2610         if (tlb->prot & (PAGE_EXEC << 4)) {
2611             ret |= 0x4;
2612         }
2613         if (tlb->prot & PAGE_READ) {
2614             ret |= 0x8;
2615         }
2616         if (tlb->prot & PAGE_WRITE) {
2617             ret |= 0x10;
2618         }
2619         if (tlb->prot & PAGE_EXEC) {
2620             ret |= 0x20;
2621         }
2622         break;
2623     }
2624     return ret;
2625 }
2626 
2627 target_ulong helper_440_tlbsx(CPUPPCState *env, target_ulong address)
2628 {
2629     return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
2630 }
2631 
2632 /* PowerPC BookE 2.06 TLB management */
2633 
2634 static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env)
2635 {
2636     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2637     uint32_t tlbncfg = 0;
2638     int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
2639     int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
2640     int tlb;
2641 
2642     tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2643     tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
2644 
2645     if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
2646         cpu_abort(CPU(cpu), "we don't support HES yet\n");
2647     }
2648 
2649     return booke206_get_tlbm(env, tlb, ea, esel);
2650 }
2651 
2652 void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid)
2653 {
2654     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2655 
2656     env->spr[pidn] = pid;
2657     /* changing PIDs mean we're in a different address space now */
2658     tlb_flush(CPU(cpu));
2659 }
2660 
2661 void helper_booke_set_eplc(CPUPPCState *env, target_ulong val)
2662 {
2663     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2664     env->spr[SPR_BOOKE_EPLC] = val & EPID_MASK;
2665     tlb_flush_by_mmuidx(CPU(cpu), 1 << PPC_TLB_EPID_LOAD);
2666 }
2667 void helper_booke_set_epsc(CPUPPCState *env, target_ulong val)
2668 {
2669     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2670     env->spr[SPR_BOOKE_EPSC] = val & EPID_MASK;
2671     tlb_flush_by_mmuidx(CPU(cpu), 1 << PPC_TLB_EPID_STORE);
2672 }
2673 
2674 static inline void flush_page(CPUPPCState *env, ppcmas_tlb_t *tlb)
2675 {
2676     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2677 
2678     if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
2679         tlb_flush_page(CPU(cpu), tlb->mas2 & MAS2_EPN_MASK);
2680     } else {
2681         tlb_flush(CPU(cpu));
2682     }
2683 }
2684 
2685 void helper_booke206_tlbwe(CPUPPCState *env)
2686 {
2687     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2688     uint32_t tlbncfg, tlbn;
2689     ppcmas_tlb_t *tlb;
2690     uint32_t size_tlb, size_ps;
2691     target_ulong mask;
2692 
2693 
2694     switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
2695     case MAS0_WQ_ALWAYS:
2696         /* good to go, write that entry */
2697         break;
2698     case MAS0_WQ_COND:
2699         /* XXX check if reserved */
2700         if (0) {
2701             return;
2702         }
2703         break;
2704     case MAS0_WQ_CLR_RSRV:
2705         /* XXX clear entry */
2706         return;
2707     default:
2708         /* no idea what to do */
2709         return;
2710     }
2711 
2712     if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
2713         !msr_gs) {
2714         /* XXX we don't support direct LRAT setting yet */
2715         fprintf(stderr, "cpu: don't support LRAT setting yet\n");
2716         return;
2717     }
2718 
2719     tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2720     tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
2721 
2722     tlb = booke206_cur_tlb(env);
2723 
2724     if (!tlb) {
2725         raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2726                                POWERPC_EXCP_INVAL |
2727                                POWERPC_EXCP_INVAL_INVAL, GETPC());
2728     }
2729 
2730     /* check that we support the targeted size */
2731     size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
2732     size_ps = booke206_tlbnps(env, tlbn);
2733     if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
2734         !(size_ps & (1 << size_tlb))) {
2735         raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2736                                POWERPC_EXCP_INVAL |
2737                                POWERPC_EXCP_INVAL_INVAL, GETPC());
2738     }
2739 
2740     if (msr_gs) {
2741         cpu_abort(CPU(cpu), "missing HV implementation\n");
2742     }
2743 
2744     if (tlb->mas1 & MAS1_VALID) {
2745         /* Invalidate the page in QEMU TLB if it was a valid entry.
2746          *
2747          * In "PowerPC e500 Core Family Reference Manual, Rev. 1",
2748          * Section "12.4.2 TLB Write Entry (tlbwe) Instruction":
2749          * (https://www.nxp.com/docs/en/reference-manual/E500CORERM.pdf)
2750          *
2751          * "Note that when an L2 TLB entry is written, it may be displacing an
2752          * already valid entry in the same L2 TLB location (a victim). If a
2753          * valid L1 TLB entry corresponds to the L2 MMU victim entry, that L1
2754          * TLB entry is automatically invalidated." */
2755         flush_page(env, tlb);
2756     }
2757 
2758     tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
2759         env->spr[SPR_BOOKE_MAS3];
2760     tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
2761 
2762     if ((env->spr[SPR_MMUCFG] & MMUCFG_MAVN) == MMUCFG_MAVN_V2) {
2763         /* For TLB which has a fixed size TSIZE is ignored with MAV2 */
2764         booke206_fixed_size_tlbn(env, tlbn, tlb);
2765     } else {
2766         if (!(tlbncfg & TLBnCFG_AVAIL)) {
2767             /* force !AVAIL TLB entries to correct page size */
2768             tlb->mas1 &= ~MAS1_TSIZE_MASK;
2769             /* XXX can be configured in MMUCSR0 */
2770             tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
2771         }
2772     }
2773 
2774     /* Make a mask from TLB size to discard invalid bits in EPN field */
2775     mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2776     /* Add a mask for page attributes */
2777     mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E;
2778 
2779     if (!msr_cm) {
2780         /* Executing a tlbwe instruction in 32-bit mode will set
2781          * bits 0:31 of the TLB EPN field to zero.
2782          */
2783         mask &= 0xffffffff;
2784     }
2785 
2786     tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask;
2787 
2788     if (!(tlbncfg & TLBnCFG_IPROT)) {
2789         /* no IPROT supported by TLB */
2790         tlb->mas1 &= ~MAS1_IPROT;
2791     }
2792 
2793     flush_page(env, tlb);
2794 }
2795 
2796 static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb)
2797 {
2798     int tlbn = booke206_tlbm_to_tlbn(env, tlb);
2799     int way = booke206_tlbm_to_way(env, tlb);
2800 
2801     env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
2802     env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
2803     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2804 
2805     env->spr[SPR_BOOKE_MAS1] = tlb->mas1;
2806     env->spr[SPR_BOOKE_MAS2] = tlb->mas2;
2807     env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3;
2808     env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32;
2809 }
2810 
2811 void helper_booke206_tlbre(CPUPPCState *env)
2812 {
2813     ppcmas_tlb_t *tlb = NULL;
2814 
2815     tlb = booke206_cur_tlb(env);
2816     if (!tlb) {
2817         env->spr[SPR_BOOKE_MAS1] = 0;
2818     } else {
2819         booke206_tlb_to_mas(env, tlb);
2820     }
2821 }
2822 
2823 void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address)
2824 {
2825     ppcmas_tlb_t *tlb = NULL;
2826     int i, j;
2827     hwaddr raddr;
2828     uint32_t spid, sas;
2829 
2830     spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
2831     sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
2832 
2833     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2834         int ways = booke206_tlb_ways(env, i);
2835 
2836         for (j = 0; j < ways; j++) {
2837             tlb = booke206_get_tlbm(env, i, address, j);
2838 
2839             if (!tlb) {
2840                 continue;
2841             }
2842 
2843             if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
2844                 continue;
2845             }
2846 
2847             if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
2848                 continue;
2849             }
2850 
2851             booke206_tlb_to_mas(env, tlb);
2852             return;
2853         }
2854     }
2855 
2856     /* no entry found, fill with defaults */
2857     env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
2858     env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
2859     env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
2860     env->spr[SPR_BOOKE_MAS3] = 0;
2861     env->spr[SPR_BOOKE_MAS7] = 0;
2862 
2863     if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
2864         env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
2865     }
2866 
2867     env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
2868         << MAS1_TID_SHIFT;
2869 
2870     /* next victim logic */
2871     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
2872     env->last_way++;
2873     env->last_way &= booke206_tlb_ways(env, 0) - 1;
2874     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2875 }
2876 
2877 static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
2878                                               uint32_t ea)
2879 {
2880     int i;
2881     int ways = booke206_tlb_ways(env, tlbn);
2882     target_ulong mask;
2883 
2884     for (i = 0; i < ways; i++) {
2885         ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
2886         if (!tlb) {
2887             continue;
2888         }
2889         mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2890         if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
2891             !(tlb->mas1 & MAS1_IPROT)) {
2892             tlb->mas1 &= ~MAS1_VALID;
2893         }
2894     }
2895 }
2896 
2897 void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
2898 {
2899     CPUState *cs;
2900 
2901     if (address & 0x4) {
2902         /* flush all entries */
2903         if (address & 0x8) {
2904             /* flush all of TLB1 */
2905             booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
2906         } else {
2907             /* flush all of TLB0 */
2908             booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
2909         }
2910         return;
2911     }
2912 
2913     if (address & 0x8) {
2914         /* flush TLB1 entries */
2915         booke206_invalidate_ea_tlb(env, 1, address);
2916         CPU_FOREACH(cs) {
2917             tlb_flush(cs);
2918         }
2919     } else {
2920         /* flush TLB0 entries */
2921         booke206_invalidate_ea_tlb(env, 0, address);
2922         CPU_FOREACH(cs) {
2923             tlb_flush_page(cs, address & MAS2_EPN_MASK);
2924         }
2925     }
2926 }
2927 
2928 void helper_booke206_tlbilx0(CPUPPCState *env, target_ulong address)
2929 {
2930     /* XXX missing LPID handling */
2931     booke206_flush_tlb(env, -1, 1);
2932 }
2933 
2934 void helper_booke206_tlbilx1(CPUPPCState *env, target_ulong address)
2935 {
2936     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2937     int i, j;
2938     int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2939     ppcmas_tlb_t *tlb = env->tlb.tlbm;
2940     int tlb_size;
2941 
2942     /* XXX missing LPID handling */
2943     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2944         tlb_size = booke206_tlb_size(env, i);
2945         for (j = 0; j < tlb_size; j++) {
2946             if (!(tlb[j].mas1 & MAS1_IPROT) &&
2947                 ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
2948                 tlb[j].mas1 &= ~MAS1_VALID;
2949             }
2950         }
2951         tlb += booke206_tlb_size(env, i);
2952     }
2953     tlb_flush(CPU(cpu));
2954 }
2955 
2956 void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address)
2957 {
2958     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2959     int i, j;
2960     ppcmas_tlb_t *tlb;
2961     int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2962     int pid = tid >> MAS6_SPID_SHIFT;
2963     int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
2964     int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
2965     /* XXX check for unsupported isize and raise an invalid opcode then */
2966     int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
2967     /* XXX implement MAV2 handling */
2968     bool mav2 = false;
2969 
2970     /* XXX missing LPID handling */
2971     /* flush by pid and ea */
2972     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2973         int ways = booke206_tlb_ways(env, i);
2974 
2975         for (j = 0; j < ways; j++) {
2976             tlb = booke206_get_tlbm(env, i, address, j);
2977             if (!tlb) {
2978                 continue;
2979             }
2980             if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
2981                 (tlb->mas1 & MAS1_IPROT) ||
2982                 ((tlb->mas1 & MAS1_IND) != ind) ||
2983                 ((tlb->mas8 & MAS8_TGS) != sgs)) {
2984                 continue;
2985             }
2986             if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
2987                 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2988                 continue;
2989             }
2990             /* XXX e500mc doesn't match SAS, but other cores might */
2991             tlb->mas1 &= ~MAS1_VALID;
2992         }
2993     }
2994     tlb_flush(CPU(cpu));
2995 }
2996 
2997 void helper_booke206_tlbflush(CPUPPCState *env, target_ulong type)
2998 {
2999     int flags = 0;
3000 
3001     if (type & 2) {
3002         flags |= BOOKE206_FLUSH_TLB1;
3003     }
3004 
3005     if (type & 4) {
3006         flags |= BOOKE206_FLUSH_TLB0;
3007     }
3008 
3009     booke206_flush_tlb(env, flags, 1);
3010 }
3011 
3012 
3013 void helper_check_tlb_flush_local(CPUPPCState *env)
3014 {
3015     check_tlb_flush(env, false);
3016 }
3017 
3018 void helper_check_tlb_flush_global(CPUPPCState *env)
3019 {
3020     check_tlb_flush(env, true);
3021 }
3022 
3023 /*****************************************************************************/
3024 
3025 /* try to fill the TLB and return an exception if error. If retaddr is
3026    NULL, it means that the function was called in C code (i.e. not
3027    from generated code or from helper.c) */
3028 /* XXX: fix it to restore all registers */
3029 void tlb_fill(CPUState *cs, target_ulong addr, int size,
3030               MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
3031 {
3032     PowerPCCPU *cpu = POWERPC_CPU(cs);
3033     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
3034     CPUPPCState *env = &cpu->env;
3035     int ret;
3036 
3037     if (pcc->handle_mmu_fault) {
3038         ret = pcc->handle_mmu_fault(cpu, addr, access_type, mmu_idx);
3039     } else {
3040         ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx);
3041     }
3042     if (unlikely(ret != 0)) {
3043         raise_exception_err_ra(env, cs->exception_index, env->error_code,
3044                                retaddr);
3045     }
3046 }
3047