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