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