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