xref: /openbmc/qemu/target/ppc/mmu_helper.c (revision 24496b8d)
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     if (((end - base) >> TARGET_PAGE_BITS) > 1024) {
1824         /* Flushing 1024 4K pages is slower than a complete flush */
1825         LOG_BATS("Flush all BATs\n");
1826         tlb_flush(CPU(cs));
1827         LOG_BATS("Flush done\n");
1828         return;
1829     }
1830     LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1831              TARGET_FMT_lx ")\n", base, end, mask);
1832     for (page = base; page != end; page += TARGET_PAGE_SIZE) {
1833         tlb_flush_page(cs, page);
1834     }
1835     LOG_BATS("Flush done\n");
1836 }
1837 #endif
1838 
1839 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1840                                   target_ulong value)
1841 {
1842     LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1843              nr, ul == 0 ? 'u' : 'l', value, env->nip);
1844 }
1845 
1846 void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1847 {
1848     target_ulong mask;
1849 #if defined(FLUSH_ALL_TLBS)
1850     PowerPCCPU *cpu = ppc_env_get_cpu(env);
1851 #endif
1852 
1853     dump_store_bat(env, 'I', 0, nr, value);
1854     if (env->IBAT[0][nr] != value) {
1855         mask = (value << 15) & 0x0FFE0000UL;
1856 #if !defined(FLUSH_ALL_TLBS)
1857         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1858 #endif
1859         /*
1860          * When storing valid upper BAT, mask BEPI and BRPN and
1861          * invalidate all TLBs covered by this BAT
1862          */
1863         mask = (value << 15) & 0x0FFE0000UL;
1864         env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1865             (value & ~0x0001FFFFUL & ~mask);
1866         env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1867             (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1868 #if !defined(FLUSH_ALL_TLBS)
1869         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1870 #else
1871         tlb_flush(CPU(cpu));
1872 #endif
1873     }
1874 }
1875 
1876 void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1877 {
1878     dump_store_bat(env, 'I', 1, nr, value);
1879     env->IBAT[1][nr] = value;
1880 }
1881 
1882 void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1883 {
1884     target_ulong mask;
1885 #if defined(FLUSH_ALL_TLBS)
1886     PowerPCCPU *cpu = ppc_env_get_cpu(env);
1887 #endif
1888 
1889     dump_store_bat(env, 'D', 0, nr, value);
1890     if (env->DBAT[0][nr] != value) {
1891         /*
1892          * When storing valid upper BAT, mask BEPI and BRPN and
1893          * invalidate all TLBs covered by this BAT
1894          */
1895         mask = (value << 15) & 0x0FFE0000UL;
1896 #if !defined(FLUSH_ALL_TLBS)
1897         do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1898 #endif
1899         mask = (value << 15) & 0x0FFE0000UL;
1900         env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1901             (value & ~0x0001FFFFUL & ~mask);
1902         env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1903             (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1904 #if !defined(FLUSH_ALL_TLBS)
1905         do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1906 #else
1907         tlb_flush(CPU(cpu));
1908 #endif
1909     }
1910 }
1911 
1912 void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1913 {
1914     dump_store_bat(env, 'D', 1, nr, value);
1915     env->DBAT[1][nr] = value;
1916 }
1917 
1918 void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
1919 {
1920     target_ulong mask;
1921 #if defined(FLUSH_ALL_TLBS)
1922     PowerPCCPU *cpu = ppc_env_get_cpu(env);
1923     int do_inval;
1924 #endif
1925 
1926     dump_store_bat(env, 'I', 0, nr, value);
1927     if (env->IBAT[0][nr] != value) {
1928 #if defined(FLUSH_ALL_TLBS)
1929         do_inval = 0;
1930 #endif
1931         mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1932         if (env->IBAT[1][nr] & 0x40) {
1933             /* Invalidate BAT only if it is valid */
1934 #if !defined(FLUSH_ALL_TLBS)
1935             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1936 #else
1937             do_inval = 1;
1938 #endif
1939         }
1940         /*
1941          * When storing valid upper BAT, mask BEPI and BRPN and
1942          * invalidate all TLBs covered by this BAT
1943          */
1944         env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1945             (value & ~0x0001FFFFUL & ~mask);
1946         env->DBAT[0][nr] = env->IBAT[0][nr];
1947         if (env->IBAT[1][nr] & 0x40) {
1948 #if !defined(FLUSH_ALL_TLBS)
1949             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1950 #else
1951             do_inval = 1;
1952 #endif
1953         }
1954 #if defined(FLUSH_ALL_TLBS)
1955         if (do_inval) {
1956             tlb_flush(CPU(cpu));
1957         }
1958 #endif
1959     }
1960 }
1961 
1962 void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
1963 {
1964 #if !defined(FLUSH_ALL_TLBS)
1965     target_ulong mask;
1966 #else
1967     PowerPCCPU *cpu = ppc_env_get_cpu(env);
1968     int do_inval;
1969 #endif
1970 
1971     dump_store_bat(env, 'I', 1, nr, value);
1972     if (env->IBAT[1][nr] != value) {
1973 #if defined(FLUSH_ALL_TLBS)
1974         do_inval = 0;
1975 #endif
1976         if (env->IBAT[1][nr] & 0x40) {
1977 #if !defined(FLUSH_ALL_TLBS)
1978             mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1979             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1980 #else
1981             do_inval = 1;
1982 #endif
1983         }
1984         if (value & 0x40) {
1985 #if !defined(FLUSH_ALL_TLBS)
1986             mask = (value << 17) & 0x0FFE0000UL;
1987             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1988 #else
1989             do_inval = 1;
1990 #endif
1991         }
1992         env->IBAT[1][nr] = value;
1993         env->DBAT[1][nr] = value;
1994 #if defined(FLUSH_ALL_TLBS)
1995         if (do_inval) {
1996             tlb_flush(CPU(cpu));
1997         }
1998 #endif
1999     }
2000 }
2001 
2002 /*****************************************************************************/
2003 /* TLB management */
2004 void ppc_tlb_invalidate_all(CPUPPCState *env)
2005 {
2006     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2007 
2008 #if defined(TARGET_PPC64)
2009     if (env->mmu_model & POWERPC_MMU_64) {
2010         env->tlb_need_flush = 0;
2011         tlb_flush(CPU(cpu));
2012     } else
2013 #endif /* defined(TARGET_PPC64) */
2014     switch (env->mmu_model) {
2015     case POWERPC_MMU_SOFT_6xx:
2016     case POWERPC_MMU_SOFT_74xx:
2017         ppc6xx_tlb_invalidate_all(env);
2018         break;
2019     case POWERPC_MMU_SOFT_4xx:
2020     case POWERPC_MMU_SOFT_4xx_Z:
2021         ppc4xx_tlb_invalidate_all(env);
2022         break;
2023     case POWERPC_MMU_REAL:
2024         cpu_abort(CPU(cpu), "No TLB for PowerPC 4xx in real mode\n");
2025         break;
2026     case POWERPC_MMU_MPC8xx:
2027         /* XXX: TODO */
2028         cpu_abort(CPU(cpu), "MPC8xx MMU model is not implemented\n");
2029         break;
2030     case POWERPC_MMU_BOOKE:
2031         tlb_flush(CPU(cpu));
2032         break;
2033     case POWERPC_MMU_BOOKE206:
2034         booke206_flush_tlb(env, -1, 0);
2035         break;
2036     case POWERPC_MMU_32B:
2037     case POWERPC_MMU_601:
2038         env->tlb_need_flush = 0;
2039         tlb_flush(CPU(cpu));
2040         break;
2041     default:
2042         /* XXX: TODO */
2043         cpu_abort(CPU(cpu), "Unknown MMU model %x\n", env->mmu_model);
2044         break;
2045     }
2046 }
2047 
2048 void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
2049 {
2050 #if !defined(FLUSH_ALL_TLBS)
2051     addr &= TARGET_PAGE_MASK;
2052 #if defined(TARGET_PPC64)
2053     if (env->mmu_model & POWERPC_MMU_64) {
2054         /* tlbie invalidate TLBs for all segments */
2055         /*
2056          * XXX: given the fact that there are too many segments to invalidate,
2057          *      and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
2058          *      we just invalidate all TLBs
2059          */
2060         env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2061     } else
2062 #endif /* defined(TARGET_PPC64) */
2063     switch (env->mmu_model) {
2064     case POWERPC_MMU_SOFT_6xx:
2065     case POWERPC_MMU_SOFT_74xx:
2066         ppc6xx_tlb_invalidate_virt(env, addr, 0);
2067         if (env->id_tlbs == 1) {
2068             ppc6xx_tlb_invalidate_virt(env, addr, 1);
2069         }
2070         break;
2071     case POWERPC_MMU_32B:
2072     case POWERPC_MMU_601:
2073         /*
2074          * Actual CPUs invalidate entire congruence classes based on
2075          * the geometry of their TLBs and some OSes take that into
2076          * account, we just mark the TLB to be flushed later (context
2077          * synchronizing event or sync instruction on 32-bit).
2078          */
2079         env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2080         break;
2081     default:
2082         /* Should never reach here with other MMU models */
2083         assert(0);
2084     }
2085 #else
2086     ppc_tlb_invalidate_all(env);
2087 #endif
2088 }
2089 
2090 /*****************************************************************************/
2091 /* Special registers manipulation */
2092 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
2093 {
2094     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2095     qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
2096     assert(!cpu->vhyp);
2097 #if defined(TARGET_PPC64)
2098     if (env->mmu_model & POWERPC_MMU_64) {
2099         target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
2100         target_ulong htabsize = value & SDR_64_HTABSIZE;
2101 
2102         if (value & ~sdr_mask) {
2103             error_report("Invalid bits 0x"TARGET_FMT_lx" set in SDR1",
2104                          value & ~sdr_mask);
2105             value &= sdr_mask;
2106         }
2107         if (htabsize > 28) {
2108             error_report("Invalid HTABSIZE 0x" TARGET_FMT_lx" stored in SDR1",
2109                          htabsize);
2110             return;
2111         }
2112     }
2113 #endif /* defined(TARGET_PPC64) */
2114     /* FIXME: Should check for valid HTABMASK values in 32-bit case */
2115     env->spr[SPR_SDR1] = value;
2116 }
2117 
2118 #if defined(TARGET_PPC64)
2119 void ppc_store_ptcr(CPUPPCState *env, target_ulong value)
2120 {
2121     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2122     target_ulong ptcr_mask = PTCR_PATB | PTCR_PATS;
2123     target_ulong patbsize = value & PTCR_PATS;
2124 
2125     qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
2126 
2127     assert(!cpu->vhyp);
2128     assert(env->mmu_model & POWERPC_MMU_3_00);
2129 
2130     if (value & ~ptcr_mask) {
2131         error_report("Invalid bits 0x"TARGET_FMT_lx" set in PTCR",
2132                      value & ~ptcr_mask);
2133         value &= ptcr_mask;
2134     }
2135 
2136     if (patbsize > 24) {
2137         error_report("Invalid Partition Table size 0x" TARGET_FMT_lx
2138                      " stored in PTCR", patbsize);
2139         return;
2140     }
2141 
2142     env->spr[SPR_PTCR] = value;
2143 }
2144 
2145 #endif /* defined(TARGET_PPC64) */
2146 
2147 /* Segment registers load and store */
2148 target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
2149 {
2150 #if defined(TARGET_PPC64)
2151     if (env->mmu_model & POWERPC_MMU_64) {
2152         /* XXX */
2153         return 0;
2154     }
2155 #endif
2156     return env->sr[sr_num];
2157 }
2158 
2159 void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
2160 {
2161     qemu_log_mask(CPU_LOG_MMU,
2162             "%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2163             (int)srnum, value, env->sr[srnum]);
2164 #if defined(TARGET_PPC64)
2165     if (env->mmu_model & POWERPC_MMU_64) {
2166         PowerPCCPU *cpu = ppc_env_get_cpu(env);
2167         uint64_t esid, vsid;
2168 
2169         /* ESID = srnum */
2170         esid = ((uint64_t)(srnum & 0xf) << 28) | SLB_ESID_V;
2171 
2172         /* VSID = VSID */
2173         vsid = (value & 0xfffffff) << 12;
2174         /* flags = flags */
2175         vsid |= ((value >> 27) & 0xf) << 8;
2176 
2177         ppc_store_slb(cpu, srnum, esid, vsid);
2178     } else
2179 #endif
2180     if (env->sr[srnum] != value) {
2181         env->sr[srnum] = value;
2182         /*
2183          * Invalidating 256MB of virtual memory in 4kB pages is way
2184          * longer than flusing the whole TLB.
2185          */
2186 #if !defined(FLUSH_ALL_TLBS) && 0
2187         {
2188             target_ulong page, end;
2189             /* Invalidate 256 MB of virtual memory */
2190             page = (16 << 20) * srnum;
2191             end = page + (16 << 20);
2192             for (; page != end; page += TARGET_PAGE_SIZE) {
2193                 tlb_flush_page(CPU(cpu), page);
2194             }
2195         }
2196 #else
2197         env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2198 #endif
2199     }
2200 }
2201 
2202 /* TLB management */
2203 void helper_tlbia(CPUPPCState *env)
2204 {
2205     ppc_tlb_invalidate_all(env);
2206 }
2207 
2208 void helper_tlbie(CPUPPCState *env, target_ulong addr)
2209 {
2210     ppc_tlb_invalidate_one(env, addr);
2211 }
2212 
2213 void helper_tlbiva(CPUPPCState *env, target_ulong addr)
2214 {
2215     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2216 
2217     /* tlbiva instruction only exists on BookE */
2218     assert(env->mmu_model == POWERPC_MMU_BOOKE);
2219     /* XXX: TODO */
2220     cpu_abort(CPU(cpu), "BookE MMU model is not implemented\n");
2221 }
2222 
2223 /* Software driven TLBs management */
2224 /* PowerPC 602/603 software TLB load instructions helpers */
2225 static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2226 {
2227     target_ulong RPN, CMP, EPN;
2228     int way;
2229 
2230     RPN = env->spr[SPR_RPA];
2231     if (is_code) {
2232         CMP = env->spr[SPR_ICMP];
2233         EPN = env->spr[SPR_IMISS];
2234     } else {
2235         CMP = env->spr[SPR_DCMP];
2236         EPN = env->spr[SPR_DMISS];
2237     }
2238     way = (env->spr[SPR_SRR1] >> 17) & 1;
2239     (void)EPN; /* avoid a compiler warning */
2240     LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2241               " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2242               RPN, way);
2243     /* Store this TLB */
2244     ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2245                      way, is_code, CMP, RPN);
2246 }
2247 
2248 void helper_6xx_tlbd(CPUPPCState *env, target_ulong EPN)
2249 {
2250     do_6xx_tlb(env, EPN, 0);
2251 }
2252 
2253 void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
2254 {
2255     do_6xx_tlb(env, EPN, 1);
2256 }
2257 
2258 /* PowerPC 74xx software TLB load instructions helpers */
2259 static void do_74xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2260 {
2261     target_ulong RPN, CMP, EPN;
2262     int way;
2263 
2264     RPN = env->spr[SPR_PTELO];
2265     CMP = env->spr[SPR_PTEHI];
2266     EPN = env->spr[SPR_TLBMISS] & ~0x3;
2267     way = env->spr[SPR_TLBMISS] & 0x3;
2268     (void)EPN; /* avoid a compiler warning */
2269     LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2270               " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2271               RPN, way);
2272     /* Store this TLB */
2273     ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2274                      way, is_code, CMP, RPN);
2275 }
2276 
2277 void helper_74xx_tlbd(CPUPPCState *env, target_ulong EPN)
2278 {
2279     do_74xx_tlb(env, EPN, 0);
2280 }
2281 
2282 void helper_74xx_tlbi(CPUPPCState *env, target_ulong EPN)
2283 {
2284     do_74xx_tlb(env, EPN, 1);
2285 }
2286 
2287 /*****************************************************************************/
2288 /* PowerPC 601 specific instructions (POWER bridge) */
2289 
2290 target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
2291 {
2292     mmu_ctx_t ctx;
2293     int nb_BATs;
2294     target_ulong ret = 0;
2295 
2296     /*
2297      * We don't have to generate many instances of this instruction,
2298      * as rac is supervisor only.
2299      *
2300      * XXX: FIX THIS: Pretend we have no BAT
2301      */
2302     nb_BATs = env->nb_BATs;
2303     env->nb_BATs = 0;
2304     if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) {
2305         ret = ctx.raddr;
2306     }
2307     env->nb_BATs = nb_BATs;
2308     return ret;
2309 }
2310 
2311 static inline target_ulong booke_tlb_to_page_size(int size)
2312 {
2313     return 1024 << (2 * size);
2314 }
2315 
2316 static inline int booke_page_size_to_tlb(target_ulong page_size)
2317 {
2318     int size;
2319 
2320     switch (page_size) {
2321     case 0x00000400UL:
2322         size = 0x0;
2323         break;
2324     case 0x00001000UL:
2325         size = 0x1;
2326         break;
2327     case 0x00004000UL:
2328         size = 0x2;
2329         break;
2330     case 0x00010000UL:
2331         size = 0x3;
2332         break;
2333     case 0x00040000UL:
2334         size = 0x4;
2335         break;
2336     case 0x00100000UL:
2337         size = 0x5;
2338         break;
2339     case 0x00400000UL:
2340         size = 0x6;
2341         break;
2342     case 0x01000000UL:
2343         size = 0x7;
2344         break;
2345     case 0x04000000UL:
2346         size = 0x8;
2347         break;
2348     case 0x10000000UL:
2349         size = 0x9;
2350         break;
2351     case 0x40000000UL:
2352         size = 0xA;
2353         break;
2354 #if defined(TARGET_PPC64)
2355     case 0x000100000000ULL:
2356         size = 0xB;
2357         break;
2358     case 0x000400000000ULL:
2359         size = 0xC;
2360         break;
2361     case 0x001000000000ULL:
2362         size = 0xD;
2363         break;
2364     case 0x004000000000ULL:
2365         size = 0xE;
2366         break;
2367     case 0x010000000000ULL:
2368         size = 0xF;
2369         break;
2370 #endif
2371     default:
2372         size = -1;
2373         break;
2374     }
2375 
2376     return size;
2377 }
2378 
2379 /* Helpers for 4xx TLB management */
2380 #define PPC4XX_TLB_ENTRY_MASK       0x0000003f  /* Mask for 64 TLB entries */
2381 
2382 #define PPC4XX_TLBHI_V              0x00000040
2383 #define PPC4XX_TLBHI_E              0x00000020
2384 #define PPC4XX_TLBHI_SIZE_MIN       0
2385 #define PPC4XX_TLBHI_SIZE_MAX       7
2386 #define PPC4XX_TLBHI_SIZE_DEFAULT   1
2387 #define PPC4XX_TLBHI_SIZE_SHIFT     7
2388 #define PPC4XX_TLBHI_SIZE_MASK      0x00000007
2389 
2390 #define PPC4XX_TLBLO_EX             0x00000200
2391 #define PPC4XX_TLBLO_WR             0x00000100
2392 #define PPC4XX_TLBLO_ATTR_MASK      0x000000FF
2393 #define PPC4XX_TLBLO_RPN_MASK       0xFFFFFC00
2394 
2395 target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry)
2396 {
2397     ppcemb_tlb_t *tlb;
2398     target_ulong ret;
2399     int size;
2400 
2401     entry &= PPC4XX_TLB_ENTRY_MASK;
2402     tlb = &env->tlb.tlbe[entry];
2403     ret = tlb->EPN;
2404     if (tlb->prot & PAGE_VALID) {
2405         ret |= PPC4XX_TLBHI_V;
2406     }
2407     size = booke_page_size_to_tlb(tlb->size);
2408     if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) {
2409         size = PPC4XX_TLBHI_SIZE_DEFAULT;
2410     }
2411     ret |= size << PPC4XX_TLBHI_SIZE_SHIFT;
2412     env->spr[SPR_40x_PID] = tlb->PID;
2413     return ret;
2414 }
2415 
2416 target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, target_ulong entry)
2417 {
2418     ppcemb_tlb_t *tlb;
2419     target_ulong ret;
2420 
2421     entry &= PPC4XX_TLB_ENTRY_MASK;
2422     tlb = &env->tlb.tlbe[entry];
2423     ret = tlb->RPN;
2424     if (tlb->prot & PAGE_EXEC) {
2425         ret |= PPC4XX_TLBLO_EX;
2426     }
2427     if (tlb->prot & PAGE_WRITE) {
2428         ret |= PPC4XX_TLBLO_WR;
2429     }
2430     return ret;
2431 }
2432 
2433 void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
2434                          target_ulong val)
2435 {
2436     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2437     CPUState *cs = CPU(cpu);
2438     ppcemb_tlb_t *tlb;
2439     target_ulong page, end;
2440 
2441     LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
2442               val);
2443     entry &= PPC4XX_TLB_ENTRY_MASK;
2444     tlb = &env->tlb.tlbe[entry];
2445     /* Invalidate previous TLB (if it's valid) */
2446     if (tlb->prot & PAGE_VALID) {
2447         end = tlb->EPN + tlb->size;
2448         LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end "
2449                   TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2450         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2451             tlb_flush_page(cs, page);
2452         }
2453     }
2454     tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
2455                                        & PPC4XX_TLBHI_SIZE_MASK);
2456     /*
2457      * We cannot handle TLB size < TARGET_PAGE_SIZE.
2458      * If this ever occurs, we should implement TARGET_PAGE_BITS_VARY
2459      */
2460     if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
2461         cpu_abort(cs, "TLB size " TARGET_FMT_lu " < %u "
2462                   "are not supported (%d)\n"
2463                   "Please implement TARGET_PAGE_BITS_VARY\n",
2464                   tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
2465     }
2466     tlb->EPN = val & ~(tlb->size - 1);
2467     if (val & PPC4XX_TLBHI_V) {
2468         tlb->prot |= PAGE_VALID;
2469         if (val & PPC4XX_TLBHI_E) {
2470             /* XXX: TO BE FIXED */
2471             cpu_abort(cs,
2472                       "Little-endian TLB entries are not supported by now\n");
2473         }
2474     } else {
2475         tlb->prot &= ~PAGE_VALID;
2476     }
2477     tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2478     LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2479               " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2480               (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2481               tlb->prot & PAGE_READ ? 'r' : '-',
2482               tlb->prot & PAGE_WRITE ? 'w' : '-',
2483               tlb->prot & PAGE_EXEC ? 'x' : '-',
2484               tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2485     /* Invalidate new TLB (if valid) */
2486     if (tlb->prot & PAGE_VALID) {
2487         end = tlb->EPN + tlb->size;
2488         LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end "
2489                   TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2490         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2491             tlb_flush_page(cs, page);
2492         }
2493     }
2494 }
2495 
2496 void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry,
2497                          target_ulong val)
2498 {
2499     ppcemb_tlb_t *tlb;
2500 
2501     LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
2502               val);
2503     entry &= PPC4XX_TLB_ENTRY_MASK;
2504     tlb = &env->tlb.tlbe[entry];
2505     tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
2506     tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
2507     tlb->prot = PAGE_READ;
2508     if (val & PPC4XX_TLBLO_EX) {
2509         tlb->prot |= PAGE_EXEC;
2510     }
2511     if (val & PPC4XX_TLBLO_WR) {
2512         tlb->prot |= PAGE_WRITE;
2513     }
2514     LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2515               " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2516               (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2517               tlb->prot & PAGE_READ ? 'r' : '-',
2518               tlb->prot & PAGE_WRITE ? 'w' : '-',
2519               tlb->prot & PAGE_EXEC ? 'x' : '-',
2520               tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2521 }
2522 
2523 target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address)
2524 {
2525     return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
2526 }
2527 
2528 /* PowerPC 440 TLB management */
2529 void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry,
2530                       target_ulong value)
2531 {
2532     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2533     ppcemb_tlb_t *tlb;
2534     target_ulong EPN, RPN, size;
2535     int do_flush_tlbs;
2536 
2537     LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n",
2538               __func__, word, (int)entry, value);
2539     do_flush_tlbs = 0;
2540     entry &= 0x3F;
2541     tlb = &env->tlb.tlbe[entry];
2542     switch (word) {
2543     default:
2544         /* Just here to please gcc */
2545     case 0:
2546         EPN = value & 0xFFFFFC00;
2547         if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) {
2548             do_flush_tlbs = 1;
2549         }
2550         tlb->EPN = EPN;
2551         size = booke_tlb_to_page_size((value >> 4) & 0xF);
2552         if ((tlb->prot & PAGE_VALID) && tlb->size < size) {
2553             do_flush_tlbs = 1;
2554         }
2555         tlb->size = size;
2556         tlb->attr &= ~0x1;
2557         tlb->attr |= (value >> 8) & 1;
2558         if (value & 0x200) {
2559             tlb->prot |= PAGE_VALID;
2560         } else {
2561             if (tlb->prot & PAGE_VALID) {
2562                 tlb->prot &= ~PAGE_VALID;
2563                 do_flush_tlbs = 1;
2564             }
2565         }
2566         tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2567         if (do_flush_tlbs) {
2568             tlb_flush(CPU(cpu));
2569         }
2570         break;
2571     case 1:
2572         RPN = value & 0xFFFFFC0F;
2573         if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) {
2574             tlb_flush(CPU(cpu));
2575         }
2576         tlb->RPN = RPN;
2577         break;
2578     case 2:
2579         tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
2580         tlb->prot = tlb->prot & PAGE_VALID;
2581         if (value & 0x1) {
2582             tlb->prot |= PAGE_READ << 4;
2583         }
2584         if (value & 0x2) {
2585             tlb->prot |= PAGE_WRITE << 4;
2586         }
2587         if (value & 0x4) {
2588             tlb->prot |= PAGE_EXEC << 4;
2589         }
2590         if (value & 0x8) {
2591             tlb->prot |= PAGE_READ;
2592         }
2593         if (value & 0x10) {
2594             tlb->prot |= PAGE_WRITE;
2595         }
2596         if (value & 0x20) {
2597             tlb->prot |= PAGE_EXEC;
2598         }
2599         break;
2600     }
2601 }
2602 
2603 target_ulong helper_440_tlbre(CPUPPCState *env, uint32_t word,
2604                               target_ulong entry)
2605 {
2606     ppcemb_tlb_t *tlb;
2607     target_ulong ret;
2608     int size;
2609 
2610     entry &= 0x3F;
2611     tlb = &env->tlb.tlbe[entry];
2612     switch (word) {
2613     default:
2614         /* Just here to please gcc */
2615     case 0:
2616         ret = tlb->EPN;
2617         size = booke_page_size_to_tlb(tlb->size);
2618         if (size < 0 || size > 0xF) {
2619             size = 1;
2620         }
2621         ret |= size << 4;
2622         if (tlb->attr & 0x1) {
2623             ret |= 0x100;
2624         }
2625         if (tlb->prot & PAGE_VALID) {
2626             ret |= 0x200;
2627         }
2628         env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2629         env->spr[SPR_440_MMUCR] |= tlb->PID;
2630         break;
2631     case 1:
2632         ret = tlb->RPN;
2633         break;
2634     case 2:
2635         ret = tlb->attr & ~0x1;
2636         if (tlb->prot & (PAGE_READ << 4)) {
2637             ret |= 0x1;
2638         }
2639         if (tlb->prot & (PAGE_WRITE << 4)) {
2640             ret |= 0x2;
2641         }
2642         if (tlb->prot & (PAGE_EXEC << 4)) {
2643             ret |= 0x4;
2644         }
2645         if (tlb->prot & PAGE_READ) {
2646             ret |= 0x8;
2647         }
2648         if (tlb->prot & PAGE_WRITE) {
2649             ret |= 0x10;
2650         }
2651         if (tlb->prot & PAGE_EXEC) {
2652             ret |= 0x20;
2653         }
2654         break;
2655     }
2656     return ret;
2657 }
2658 
2659 target_ulong helper_440_tlbsx(CPUPPCState *env, target_ulong address)
2660 {
2661     return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
2662 }
2663 
2664 /* PowerPC BookE 2.06 TLB management */
2665 
2666 static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env)
2667 {
2668     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2669     uint32_t tlbncfg = 0;
2670     int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
2671     int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
2672     int tlb;
2673 
2674     tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2675     tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
2676 
2677     if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
2678         cpu_abort(CPU(cpu), "we don't support HES yet\n");
2679     }
2680 
2681     return booke206_get_tlbm(env, tlb, ea, esel);
2682 }
2683 
2684 void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid)
2685 {
2686     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2687 
2688     env->spr[pidn] = pid;
2689     /* changing PIDs mean we're in a different address space now */
2690     tlb_flush(CPU(cpu));
2691 }
2692 
2693 void helper_booke_set_eplc(CPUPPCState *env, target_ulong val)
2694 {
2695     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2696     env->spr[SPR_BOOKE_EPLC] = val & EPID_MASK;
2697     tlb_flush_by_mmuidx(CPU(cpu), 1 << PPC_TLB_EPID_LOAD);
2698 }
2699 void helper_booke_set_epsc(CPUPPCState *env, target_ulong val)
2700 {
2701     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2702     env->spr[SPR_BOOKE_EPSC] = val & EPID_MASK;
2703     tlb_flush_by_mmuidx(CPU(cpu), 1 << PPC_TLB_EPID_STORE);
2704 }
2705 
2706 static inline void flush_page(CPUPPCState *env, ppcmas_tlb_t *tlb)
2707 {
2708     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2709 
2710     if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
2711         tlb_flush_page(CPU(cpu), tlb->mas2 & MAS2_EPN_MASK);
2712     } else {
2713         tlb_flush(CPU(cpu));
2714     }
2715 }
2716 
2717 void helper_booke206_tlbwe(CPUPPCState *env)
2718 {
2719     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2720     uint32_t tlbncfg, tlbn;
2721     ppcmas_tlb_t *tlb;
2722     uint32_t size_tlb, size_ps;
2723     target_ulong mask;
2724 
2725 
2726     switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
2727     case MAS0_WQ_ALWAYS:
2728         /* good to go, write that entry */
2729         break;
2730     case MAS0_WQ_COND:
2731         /* XXX check if reserved */
2732         if (0) {
2733             return;
2734         }
2735         break;
2736     case MAS0_WQ_CLR_RSRV:
2737         /* XXX clear entry */
2738         return;
2739     default:
2740         /* no idea what to do */
2741         return;
2742     }
2743 
2744     if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
2745         !msr_gs) {
2746         /* XXX we don't support direct LRAT setting yet */
2747         fprintf(stderr, "cpu: don't support LRAT setting yet\n");
2748         return;
2749     }
2750 
2751     tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2752     tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
2753 
2754     tlb = booke206_cur_tlb(env);
2755 
2756     if (!tlb) {
2757         raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2758                                POWERPC_EXCP_INVAL |
2759                                POWERPC_EXCP_INVAL_INVAL, GETPC());
2760     }
2761 
2762     /* check that we support the targeted size */
2763     size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
2764     size_ps = booke206_tlbnps(env, tlbn);
2765     if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
2766         !(size_ps & (1 << size_tlb))) {
2767         raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2768                                POWERPC_EXCP_INVAL |
2769                                POWERPC_EXCP_INVAL_INVAL, GETPC());
2770     }
2771 
2772     if (msr_gs) {
2773         cpu_abort(CPU(cpu), "missing HV implementation\n");
2774     }
2775 
2776     if (tlb->mas1 & MAS1_VALID) {
2777         /*
2778          * Invalidate the page in QEMU TLB if it was a valid entry.
2779          *
2780          * In "PowerPC e500 Core Family Reference Manual, Rev. 1",
2781          * Section "12.4.2 TLB Write Entry (tlbwe) Instruction":
2782          * (https://www.nxp.com/docs/en/reference-manual/E500CORERM.pdf)
2783          *
2784          * "Note that when an L2 TLB entry is written, it may be displacing an
2785          * already valid entry in the same L2 TLB location (a victim). If a
2786          * valid L1 TLB entry corresponds to the L2 MMU victim entry, that L1
2787          * TLB entry is automatically invalidated."
2788          */
2789         flush_page(env, tlb);
2790     }
2791 
2792     tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
2793         env->spr[SPR_BOOKE_MAS3];
2794     tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
2795 
2796     if ((env->spr[SPR_MMUCFG] & MMUCFG_MAVN) == MMUCFG_MAVN_V2) {
2797         /* For TLB which has a fixed size TSIZE is ignored with MAV2 */
2798         booke206_fixed_size_tlbn(env, tlbn, tlb);
2799     } else {
2800         if (!(tlbncfg & TLBnCFG_AVAIL)) {
2801             /* force !AVAIL TLB entries to correct page size */
2802             tlb->mas1 &= ~MAS1_TSIZE_MASK;
2803             /* XXX can be configured in MMUCSR0 */
2804             tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
2805         }
2806     }
2807 
2808     /* Make a mask from TLB size to discard invalid bits in EPN field */
2809     mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2810     /* Add a mask for page attributes */
2811     mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E;
2812 
2813     if (!msr_cm) {
2814         /*
2815          * Executing a tlbwe instruction in 32-bit mode will set bits
2816          * 0:31 of the TLB EPN field to zero.
2817          */
2818         mask &= 0xffffffff;
2819     }
2820 
2821     tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask;
2822 
2823     if (!(tlbncfg & TLBnCFG_IPROT)) {
2824         /* no IPROT supported by TLB */
2825         tlb->mas1 &= ~MAS1_IPROT;
2826     }
2827 
2828     flush_page(env, tlb);
2829 }
2830 
2831 static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb)
2832 {
2833     int tlbn = booke206_tlbm_to_tlbn(env, tlb);
2834     int way = booke206_tlbm_to_way(env, tlb);
2835 
2836     env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
2837     env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
2838     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2839 
2840     env->spr[SPR_BOOKE_MAS1] = tlb->mas1;
2841     env->spr[SPR_BOOKE_MAS2] = tlb->mas2;
2842     env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3;
2843     env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32;
2844 }
2845 
2846 void helper_booke206_tlbre(CPUPPCState *env)
2847 {
2848     ppcmas_tlb_t *tlb = NULL;
2849 
2850     tlb = booke206_cur_tlb(env);
2851     if (!tlb) {
2852         env->spr[SPR_BOOKE_MAS1] = 0;
2853     } else {
2854         booke206_tlb_to_mas(env, tlb);
2855     }
2856 }
2857 
2858 void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address)
2859 {
2860     ppcmas_tlb_t *tlb = NULL;
2861     int i, j;
2862     hwaddr raddr;
2863     uint32_t spid, sas;
2864 
2865     spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
2866     sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
2867 
2868     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2869         int ways = booke206_tlb_ways(env, i);
2870 
2871         for (j = 0; j < ways; j++) {
2872             tlb = booke206_get_tlbm(env, i, address, j);
2873 
2874             if (!tlb) {
2875                 continue;
2876             }
2877 
2878             if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
2879                 continue;
2880             }
2881 
2882             if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
2883                 continue;
2884             }
2885 
2886             booke206_tlb_to_mas(env, tlb);
2887             return;
2888         }
2889     }
2890 
2891     /* no entry found, fill with defaults */
2892     env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
2893     env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
2894     env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
2895     env->spr[SPR_BOOKE_MAS3] = 0;
2896     env->spr[SPR_BOOKE_MAS7] = 0;
2897 
2898     if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
2899         env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
2900     }
2901 
2902     env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
2903         << MAS1_TID_SHIFT;
2904 
2905     /* next victim logic */
2906     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
2907     env->last_way++;
2908     env->last_way &= booke206_tlb_ways(env, 0) - 1;
2909     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2910 }
2911 
2912 static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
2913                                               uint32_t ea)
2914 {
2915     int i;
2916     int ways = booke206_tlb_ways(env, tlbn);
2917     target_ulong mask;
2918 
2919     for (i = 0; i < ways; i++) {
2920         ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
2921         if (!tlb) {
2922             continue;
2923         }
2924         mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2925         if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
2926             !(tlb->mas1 & MAS1_IPROT)) {
2927             tlb->mas1 &= ~MAS1_VALID;
2928         }
2929     }
2930 }
2931 
2932 void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
2933 {
2934     CPUState *cs;
2935 
2936     if (address & 0x4) {
2937         /* flush all entries */
2938         if (address & 0x8) {
2939             /* flush all of TLB1 */
2940             booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
2941         } else {
2942             /* flush all of TLB0 */
2943             booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
2944         }
2945         return;
2946     }
2947 
2948     if (address & 0x8) {
2949         /* flush TLB1 entries */
2950         booke206_invalidate_ea_tlb(env, 1, address);
2951         CPU_FOREACH(cs) {
2952             tlb_flush(cs);
2953         }
2954     } else {
2955         /* flush TLB0 entries */
2956         booke206_invalidate_ea_tlb(env, 0, address);
2957         CPU_FOREACH(cs) {
2958             tlb_flush_page(cs, address & MAS2_EPN_MASK);
2959         }
2960     }
2961 }
2962 
2963 void helper_booke206_tlbilx0(CPUPPCState *env, target_ulong address)
2964 {
2965     /* XXX missing LPID handling */
2966     booke206_flush_tlb(env, -1, 1);
2967 }
2968 
2969 void helper_booke206_tlbilx1(CPUPPCState *env, target_ulong address)
2970 {
2971     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2972     int i, j;
2973     int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2974     ppcmas_tlb_t *tlb = env->tlb.tlbm;
2975     int tlb_size;
2976 
2977     /* XXX missing LPID handling */
2978     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2979         tlb_size = booke206_tlb_size(env, i);
2980         for (j = 0; j < tlb_size; j++) {
2981             if (!(tlb[j].mas1 & MAS1_IPROT) &&
2982                 ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
2983                 tlb[j].mas1 &= ~MAS1_VALID;
2984             }
2985         }
2986         tlb += booke206_tlb_size(env, i);
2987     }
2988     tlb_flush(CPU(cpu));
2989 }
2990 
2991 void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address)
2992 {
2993     PowerPCCPU *cpu = ppc_env_get_cpu(env);
2994     int i, j;
2995     ppcmas_tlb_t *tlb;
2996     int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2997     int pid = tid >> MAS6_SPID_SHIFT;
2998     int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
2999     int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
3000     /* XXX check for unsupported isize and raise an invalid opcode then */
3001     int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
3002     /* XXX implement MAV2 handling */
3003     bool mav2 = false;
3004 
3005     /* XXX missing LPID handling */
3006     /* flush by pid and ea */
3007     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
3008         int ways = booke206_tlb_ways(env, i);
3009 
3010         for (j = 0; j < ways; j++) {
3011             tlb = booke206_get_tlbm(env, i, address, j);
3012             if (!tlb) {
3013                 continue;
3014             }
3015             if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
3016                 (tlb->mas1 & MAS1_IPROT) ||
3017                 ((tlb->mas1 & MAS1_IND) != ind) ||
3018                 ((tlb->mas8 & MAS8_TGS) != sgs)) {
3019                 continue;
3020             }
3021             if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
3022                 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
3023                 continue;
3024             }
3025             /* XXX e500mc doesn't match SAS, but other cores might */
3026             tlb->mas1 &= ~MAS1_VALID;
3027         }
3028     }
3029     tlb_flush(CPU(cpu));
3030 }
3031 
3032 void helper_booke206_tlbflush(CPUPPCState *env, target_ulong type)
3033 {
3034     int flags = 0;
3035 
3036     if (type & 2) {
3037         flags |= BOOKE206_FLUSH_TLB1;
3038     }
3039 
3040     if (type & 4) {
3041         flags |= BOOKE206_FLUSH_TLB0;
3042     }
3043 
3044     booke206_flush_tlb(env, flags, 1);
3045 }
3046 
3047 
3048 void helper_check_tlb_flush_local(CPUPPCState *env)
3049 {
3050     check_tlb_flush(env, false);
3051 }
3052 
3053 void helper_check_tlb_flush_global(CPUPPCState *env)
3054 {
3055     check_tlb_flush(env, true);
3056 }
3057 
3058 /*****************************************************************************/
3059 
3060 /*
3061  * try to fill the TLB and return an exception if error. If retaddr is
3062  * NULL, it means that the function was called in C code (i.e. not
3063  * from generated code or from helper.c)
3064  *
3065  * XXX: fix it to restore all registers
3066  */
3067 void tlb_fill(CPUState *cs, target_ulong addr, int size,
3068               MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
3069 {
3070     PowerPCCPU *cpu = POWERPC_CPU(cs);
3071     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
3072     CPUPPCState *env = &cpu->env;
3073     int ret;
3074 
3075     if (pcc->handle_mmu_fault) {
3076         ret = pcc->handle_mmu_fault(cpu, addr, access_type, mmu_idx);
3077     } else {
3078         ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx);
3079     }
3080     if (unlikely(ret != 0)) {
3081         raise_exception_err_ra(env, cs->exception_index, env->error_code,
3082                                retaddr);
3083     }
3084 }
3085