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