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