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