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