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