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