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