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