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