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