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