]> Git Repo - qemu.git/blob - target-ppc/helper.c
Merge branch 'malta' of git://qemu.weilnetz.de/qemu
[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 mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf,
1470                                      CPUPPCState *env, int tlbn, int offset,
1471                                      int tlbsize)
1472 {
1473     ppcmas_tlb_t *entry;
1474     int i;
1475
1476     cpu_fprintf(f, "\nTLB%d:\n", tlbn);
1477     cpu_fprintf(f, "Effective          Physical           Size TID   TS SRWX URWX WIMGE U0123\n");
1478
1479     entry = &env->tlb.tlbm[offset];
1480     for (i = 0; i < tlbsize; i++, entry++) {
1481         target_phys_addr_t ea, pa, size;
1482         int tsize;
1483
1484         if (!(entry->mas1 & MAS1_VALID)) {
1485             continue;
1486         }
1487
1488         tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1489         size = 1024ULL << tsize;
1490         ea = entry->mas2 & ~(size - 1);
1491         pa = entry->mas7_3 & ~(size - 1);
1492
1493         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",
1494                     (uint64_t)ea, (uint64_t)pa,
1495                     book3e_tsize_to_str[tsize],
1496                     (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
1497                     (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
1498                     entry->mas7_3 & MAS3_SR ? 'R' : '-',
1499                     entry->mas7_3 & MAS3_SW ? 'W' : '-',
1500                     entry->mas7_3 & MAS3_SX ? 'X' : '-',
1501                     entry->mas7_3 & MAS3_UR ? 'R' : '-',
1502                     entry->mas7_3 & MAS3_UW ? 'W' : '-',
1503                     entry->mas7_3 & MAS3_UX ? 'X' : '-',
1504                     entry->mas2 & MAS2_W ? 'W' : '-',
1505                     entry->mas2 & MAS2_I ? 'I' : '-',
1506                     entry->mas2 & MAS2_M ? 'M' : '-',
1507                     entry->mas2 & MAS2_G ? 'G' : '-',
1508                     entry->mas2 & MAS2_E ? 'E' : '-',
1509                     entry->mas7_3 & MAS3_U0 ? '0' : '-',
1510                     entry->mas7_3 & MAS3_U1 ? '1' : '-',
1511                     entry->mas7_3 & MAS3_U2 ? '2' : '-',
1512                     entry->mas7_3 & MAS3_U3 ? '3' : '-');
1513     }
1514 }
1515
1516 static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1517                                  CPUPPCState *env)
1518 {
1519     int offset = 0;
1520     int i;
1521
1522     if (kvm_enabled() && !env->kvm_sw_tlb) {
1523         cpu_fprintf(f, "Cannot access KVM TLB\n");
1524         return;
1525     }
1526
1527     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1528         int size = booke206_tlb_size(env, i);
1529
1530         if (size == 0) {
1531             continue;
1532         }
1533
1534         mmubooke206_dump_one_tlb(f, cpu_fprintf, env, i, offset, size);
1535         offset += size;
1536     }
1537 }
1538
1539 #if defined(TARGET_PPC64)
1540 static void mmubooks_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1541                               CPUPPCState *env)
1542 {
1543     int i;
1544     uint64_t slbe, slbv;
1545
1546     cpu_synchronize_state(env);
1547
1548     cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n");
1549     for (i = 0; i < env->slb_nr; i++) {
1550         slbe = env->slb[i].esid;
1551         slbv = env->slb[i].vsid;
1552         if (slbe == 0 && slbv == 0) {
1553             continue;
1554         }
1555         cpu_fprintf(f, "%d\t0x%016" PRIx64 "\t0x%016" PRIx64 "\n",
1556                     i, slbe, slbv);
1557     }
1558 }
1559 #endif
1560
1561 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
1562 {
1563     switch (env->mmu_model) {
1564     case POWERPC_MMU_BOOKE206:
1565         mmubooke206_dump_mmu(f, cpu_fprintf, env);
1566         break;
1567 #if defined(TARGET_PPC64)
1568     case POWERPC_MMU_64B:
1569     case POWERPC_MMU_2_06:
1570         mmubooks_dump_mmu(f, cpu_fprintf, env);
1571         break;
1572 #endif
1573     default:
1574         cpu_fprintf(f, "%s: unimplemented\n", __func__);
1575     }
1576 }
1577
1578 static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
1579                                  target_ulong eaddr, int rw)
1580 {
1581     int in_plb, ret;
1582
1583     ctx->raddr = eaddr;
1584     ctx->prot = PAGE_READ | PAGE_EXEC;
1585     ret = 0;
1586     switch (env->mmu_model) {
1587     case POWERPC_MMU_32B:
1588     case POWERPC_MMU_601:
1589     case POWERPC_MMU_SOFT_6xx:
1590     case POWERPC_MMU_SOFT_74xx:
1591     case POWERPC_MMU_SOFT_4xx:
1592     case POWERPC_MMU_REAL:
1593     case POWERPC_MMU_BOOKE:
1594         ctx->prot |= PAGE_WRITE;
1595         break;
1596 #if defined(TARGET_PPC64)
1597     case POWERPC_MMU_620:
1598     case POWERPC_MMU_64B:
1599     case POWERPC_MMU_2_06:
1600         /* Real address are 60 bits long */
1601         ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1602         ctx->prot |= PAGE_WRITE;
1603         break;
1604 #endif
1605     case POWERPC_MMU_SOFT_4xx_Z:
1606         if (unlikely(msr_pe != 0)) {
1607             /* 403 family add some particular protections,
1608              * using PBL/PBU registers for accesses with no translation.
1609              */
1610             in_plb =
1611                 /* Check PLB validity */
1612                 (env->pb[0] < env->pb[1] &&
1613                  /* and address in plb area */
1614                  eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1615                 (env->pb[2] < env->pb[3] &&
1616                  eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1617             if (in_plb ^ msr_px) {
1618                 /* Access in protected area */
1619                 if (rw == 1) {
1620                     /* Access is not allowed */
1621                     ret = -2;
1622                 }
1623             } else {
1624                 /* Read-write access is allowed */
1625                 ctx->prot |= PAGE_WRITE;
1626             }
1627         }
1628         break;
1629     case POWERPC_MMU_MPC8xx:
1630         /* XXX: TODO */
1631         cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1632         break;
1633     case POWERPC_MMU_BOOKE206:
1634         cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
1635         break;
1636     default:
1637         cpu_abort(env, "Unknown or invalid MMU model\n");
1638         return -1;
1639     }
1640
1641     return ret;
1642 }
1643
1644 int get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1645                           int rw, int access_type)
1646 {
1647     int ret;
1648
1649 #if 0
1650     qemu_log("%s\n", __func__);
1651 #endif
1652     if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1653         (access_type != ACCESS_CODE && msr_dr == 0)) {
1654         if (env->mmu_model == POWERPC_MMU_BOOKE) {
1655             /* The BookE MMU always performs address translation. The
1656                IS and DS bits only affect the address space.  */
1657             ret = mmubooke_get_physical_address(env, ctx, eaddr,
1658                                                 rw, access_type);
1659         } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1660             ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1661                                                    access_type);
1662         } else {
1663             /* No address translation.  */
1664             ret = check_physical(env, ctx, eaddr, rw);
1665         }
1666     } else {
1667         ret = -1;
1668         switch (env->mmu_model) {
1669         case POWERPC_MMU_32B:
1670         case POWERPC_MMU_601:
1671         case POWERPC_MMU_SOFT_6xx:
1672         case POWERPC_MMU_SOFT_74xx:
1673             /* Try to find a BAT */
1674             if (env->nb_BATs != 0)
1675                 ret = get_bat(env, ctx, eaddr, rw, access_type);
1676 #if defined(TARGET_PPC64)
1677         case POWERPC_MMU_620:
1678         case POWERPC_MMU_64B:
1679         case POWERPC_MMU_2_06:
1680 #endif
1681             if (ret < 0) {
1682                 /* We didn't match any BAT entry or don't have BATs */
1683                 ret = get_segment(env, ctx, eaddr, rw, access_type);
1684             }
1685             break;
1686         case POWERPC_MMU_SOFT_4xx:
1687         case POWERPC_MMU_SOFT_4xx_Z:
1688             ret = mmu40x_get_physical_address(env, ctx, eaddr,
1689                                               rw, access_type);
1690             break;
1691         case POWERPC_MMU_BOOKE:
1692             ret = mmubooke_get_physical_address(env, ctx, eaddr,
1693                                                 rw, access_type);
1694             break;
1695         case POWERPC_MMU_BOOKE206:
1696             ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1697                                                access_type);
1698             break;
1699         case POWERPC_MMU_MPC8xx:
1700             /* XXX: TODO */
1701             cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1702             break;
1703         case POWERPC_MMU_REAL:
1704             cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1705             return -1;
1706         default:
1707             cpu_abort(env, "Unknown or invalid MMU model\n");
1708             return -1;
1709         }
1710     }
1711 #if 0
1712     qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1713              __func__, eaddr, ret, ctx->raddr);
1714 #endif
1715
1716     return ret;
1717 }
1718
1719 target_phys_addr_t cpu_get_phys_page_debug (CPUPPCState *env, target_ulong addr)
1720 {
1721     mmu_ctx_t ctx;
1722
1723     if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1724         return -1;
1725
1726     return ctx.raddr & TARGET_PAGE_MASK;
1727 }
1728
1729 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
1730                                      int rw)
1731 {
1732     env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1733     env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1734     env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1735     env->spr[SPR_BOOKE_MAS3] = 0;
1736     env->spr[SPR_BOOKE_MAS6] = 0;
1737     env->spr[SPR_BOOKE_MAS7] = 0;
1738
1739     /* AS */
1740     if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1741         env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1742         env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1743     }
1744
1745     env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1746     env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1747
1748     switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1749     case MAS4_TIDSELD_PID0:
1750         env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1751         break;
1752     case MAS4_TIDSELD_PID1:
1753         env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1754         break;
1755     case MAS4_TIDSELD_PID2:
1756         env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1757         break;
1758     }
1759
1760     env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1761
1762     /* next victim logic */
1763     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1764     env->last_way++;
1765     env->last_way &= booke206_tlb_ways(env, 0) - 1;
1766     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1767 }
1768
1769 /* Perform address translation */
1770 int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
1771                               int mmu_idx)
1772 {
1773     mmu_ctx_t ctx;
1774     int access_type;
1775     int ret = 0;
1776
1777     if (rw == 2) {
1778         /* code access */
1779         rw = 0;
1780         access_type = ACCESS_CODE;
1781     } else {
1782         /* data access */
1783         access_type = env->access_type;
1784     }
1785     ret = get_physical_address(env, &ctx, address, rw, access_type);
1786     if (ret == 0) {
1787         tlb_set_page(env, address & TARGET_PAGE_MASK,
1788                      ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1789                      mmu_idx, TARGET_PAGE_SIZE);
1790         ret = 0;
1791     } else if (ret < 0) {
1792         LOG_MMU_STATE(env);
1793         if (access_type == ACCESS_CODE) {
1794             switch (ret) {
1795             case -1:
1796                 /* No matches in page tables or TLB */
1797                 switch (env->mmu_model) {
1798                 case POWERPC_MMU_SOFT_6xx:
1799                     env->exception_index = POWERPC_EXCP_IFTLB;
1800                     env->error_code = 1 << 18;
1801                     env->spr[SPR_IMISS] = address;
1802                     env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1803                     goto tlb_miss;
1804                 case POWERPC_MMU_SOFT_74xx:
1805                     env->exception_index = POWERPC_EXCP_IFTLB;
1806                     goto tlb_miss_74xx;
1807                 case POWERPC_MMU_SOFT_4xx:
1808                 case POWERPC_MMU_SOFT_4xx_Z:
1809                     env->exception_index = POWERPC_EXCP_ITLB;
1810                     env->error_code = 0;
1811                     env->spr[SPR_40x_DEAR] = address;
1812                     env->spr[SPR_40x_ESR] = 0x00000000;
1813                     break;
1814                 case POWERPC_MMU_32B:
1815                 case POWERPC_MMU_601:
1816 #if defined(TARGET_PPC64)
1817                 case POWERPC_MMU_620:
1818                 case POWERPC_MMU_64B:
1819                 case POWERPC_MMU_2_06:
1820 #endif
1821                     env->exception_index = POWERPC_EXCP_ISI;
1822                     env->error_code = 0x40000000;
1823                     break;
1824                 case POWERPC_MMU_BOOKE206:
1825                     booke206_update_mas_tlb_miss(env, address, rw);
1826                     /* fall through */
1827                 case POWERPC_MMU_BOOKE:
1828                     env->exception_index = POWERPC_EXCP_ITLB;
1829                     env->error_code = 0;
1830                     env->spr[SPR_BOOKE_DEAR] = address;
1831                     return -1;
1832                 case POWERPC_MMU_MPC8xx:
1833                     /* XXX: TODO */
1834                     cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1835                     break;
1836                 case POWERPC_MMU_REAL:
1837                     cpu_abort(env, "PowerPC in real mode should never raise "
1838                               "any MMU exceptions\n");
1839                     return -1;
1840                 default:
1841                     cpu_abort(env, "Unknown or invalid MMU model\n");
1842                     return -1;
1843                 }
1844                 break;
1845             case -2:
1846                 /* Access rights violation */
1847                 env->exception_index = POWERPC_EXCP_ISI;
1848                 env->error_code = 0x08000000;
1849                 break;
1850             case -3:
1851                 /* No execute protection violation */
1852                 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1853                     (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1854                     env->spr[SPR_BOOKE_ESR] = 0x00000000;
1855                 }
1856                 env->exception_index = POWERPC_EXCP_ISI;
1857                 env->error_code = 0x10000000;
1858                 break;
1859             case -4:
1860                 /* Direct store exception */
1861                 /* No code fetch is allowed in direct-store areas */
1862                 env->exception_index = POWERPC_EXCP_ISI;
1863                 env->error_code = 0x10000000;
1864                 break;
1865 #if defined(TARGET_PPC64)
1866             case -5:
1867                 /* No match in segment table */
1868                 if (env->mmu_model == POWERPC_MMU_620) {
1869                     env->exception_index = POWERPC_EXCP_ISI;
1870                     /* XXX: this might be incorrect */
1871                     env->error_code = 0x40000000;
1872                 } else {
1873                     env->exception_index = POWERPC_EXCP_ISEG;
1874                     env->error_code = 0;
1875                 }
1876                 break;
1877 #endif
1878             }
1879         } else {
1880             switch (ret) {
1881             case -1:
1882                 /* No matches in page tables or TLB */
1883                 switch (env->mmu_model) {
1884                 case POWERPC_MMU_SOFT_6xx:
1885                     if (rw == 1) {
1886                         env->exception_index = POWERPC_EXCP_DSTLB;
1887                         env->error_code = 1 << 16;
1888                     } else {
1889                         env->exception_index = POWERPC_EXCP_DLTLB;
1890                         env->error_code = 0;
1891                     }
1892                     env->spr[SPR_DMISS] = address;
1893                     env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1894                 tlb_miss:
1895                     env->error_code |= ctx.key << 19;
1896                     env->spr[SPR_HASH1] = env->htab_base +
1897                         get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1898                     env->spr[SPR_HASH2] = env->htab_base +
1899                         get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1900                     break;
1901                 case POWERPC_MMU_SOFT_74xx:
1902                     if (rw == 1) {
1903                         env->exception_index = POWERPC_EXCP_DSTLB;
1904                     } else {
1905                         env->exception_index = POWERPC_EXCP_DLTLB;
1906                     }
1907                 tlb_miss_74xx:
1908                     /* Implement LRU algorithm */
1909                     env->error_code = ctx.key << 19;
1910                     env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1911                         ((env->last_way + 1) & (env->nb_ways - 1));
1912                     env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1913                     break;
1914                 case POWERPC_MMU_SOFT_4xx:
1915                 case POWERPC_MMU_SOFT_4xx_Z:
1916                     env->exception_index = POWERPC_EXCP_DTLB;
1917                     env->error_code = 0;
1918                     env->spr[SPR_40x_DEAR] = address;
1919                     if (rw)
1920                         env->spr[SPR_40x_ESR] = 0x00800000;
1921                     else
1922                         env->spr[SPR_40x_ESR] = 0x00000000;
1923                     break;
1924                 case POWERPC_MMU_32B:
1925                 case POWERPC_MMU_601:
1926 #if defined(TARGET_PPC64)
1927                 case POWERPC_MMU_620:
1928                 case POWERPC_MMU_64B:
1929                 case POWERPC_MMU_2_06:
1930 #endif
1931                     env->exception_index = POWERPC_EXCP_DSI;
1932                     env->error_code = 0;
1933                     env->spr[SPR_DAR] = address;
1934                     if (rw == 1)
1935                         env->spr[SPR_DSISR] = 0x42000000;
1936                     else
1937                         env->spr[SPR_DSISR] = 0x40000000;
1938                     break;
1939                 case POWERPC_MMU_MPC8xx:
1940                     /* XXX: TODO */
1941                     cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1942                     break;
1943                 case POWERPC_MMU_BOOKE206:
1944                     booke206_update_mas_tlb_miss(env, address, rw);
1945                     /* fall through */
1946                 case POWERPC_MMU_BOOKE:
1947                     env->exception_index = POWERPC_EXCP_DTLB;
1948                     env->error_code = 0;
1949                     env->spr[SPR_BOOKE_DEAR] = address;
1950                     env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1951                     return -1;
1952                 case POWERPC_MMU_REAL:
1953                     cpu_abort(env, "PowerPC in real mode should never raise "
1954                               "any MMU exceptions\n");
1955                     return -1;
1956                 default:
1957                     cpu_abort(env, "Unknown or invalid MMU model\n");
1958                     return -1;
1959                 }
1960                 break;
1961             case -2:
1962                 /* Access rights violation */
1963                 env->exception_index = POWERPC_EXCP_DSI;
1964                 env->error_code = 0;
1965                 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1966                     || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1967                     env->spr[SPR_40x_DEAR] = address;
1968                     if (rw) {
1969                         env->spr[SPR_40x_ESR] |= 0x00800000;
1970                     }
1971                 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1972                            (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1973                     env->spr[SPR_BOOKE_DEAR] = address;
1974                     env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1975                 } else {
1976                     env->spr[SPR_DAR] = address;
1977                     if (rw == 1) {
1978                         env->spr[SPR_DSISR] = 0x0A000000;
1979                     } else {
1980                         env->spr[SPR_DSISR] = 0x08000000;
1981                     }
1982                 }
1983                 break;
1984             case -4:
1985                 /* Direct store exception */
1986                 switch (access_type) {
1987                 case ACCESS_FLOAT:
1988                     /* Floating point load/store */
1989                     env->exception_index = POWERPC_EXCP_ALIGN;
1990                     env->error_code = POWERPC_EXCP_ALIGN_FP;
1991                     env->spr[SPR_DAR] = address;
1992                     break;
1993                 case ACCESS_RES:
1994                     /* lwarx, ldarx or stwcx. */
1995                     env->exception_index = POWERPC_EXCP_DSI;
1996                     env->error_code = 0;
1997                     env->spr[SPR_DAR] = address;
1998                     if (rw == 1)
1999                         env->spr[SPR_DSISR] = 0x06000000;
2000                     else
2001                         env->spr[SPR_DSISR] = 0x04000000;
2002                     break;
2003                 case ACCESS_EXT:
2004                     /* eciwx or ecowx */
2005                     env->exception_index = POWERPC_EXCP_DSI;
2006                     env->error_code = 0;
2007                     env->spr[SPR_DAR] = address;
2008                     if (rw == 1)
2009                         env->spr[SPR_DSISR] = 0x06100000;
2010                     else
2011                         env->spr[SPR_DSISR] = 0x04100000;
2012                     break;
2013                 default:
2014                     printf("DSI: invalid exception (%d)\n", ret);
2015                     env->exception_index = POWERPC_EXCP_PROGRAM;
2016                     env->error_code =
2017                         POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
2018                     env->spr[SPR_DAR] = address;
2019                     break;
2020                 }
2021                 break;
2022 #if defined(TARGET_PPC64)
2023             case -5:
2024                 /* No match in segment table */
2025                 if (env->mmu_model == POWERPC_MMU_620) {
2026                     env->exception_index = POWERPC_EXCP_DSI;
2027                     env->error_code = 0;
2028                     env->spr[SPR_DAR] = address;
2029                     /* XXX: this might be incorrect */
2030                     if (rw == 1)
2031                         env->spr[SPR_DSISR] = 0x42000000;
2032                     else
2033                         env->spr[SPR_DSISR] = 0x40000000;
2034                 } else {
2035                     env->exception_index = POWERPC_EXCP_DSEG;
2036                     env->error_code = 0;
2037                     env->spr[SPR_DAR] = address;
2038                 }
2039                 break;
2040 #endif
2041             }
2042         }
2043 #if 0
2044         printf("%s: set exception to %d %02x\n", __func__,
2045                env->exception, env->error_code);
2046 #endif
2047         ret = 1;
2048     }
2049
2050     return ret;
2051 }
2052
2053 /*****************************************************************************/
2054 /* BATs management */
2055 #if !defined(FLUSH_ALL_TLBS)
2056 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
2057                                      target_ulong mask)
2058 {
2059     target_ulong base, end, page;
2060
2061     base = BATu & ~0x0001FFFF;
2062     end = base + mask + 0x00020000;
2063     LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
2064              TARGET_FMT_lx ")\n", base, end, mask);
2065     for (page = base; page != end; page += TARGET_PAGE_SIZE)
2066         tlb_flush_page(env, page);
2067     LOG_BATS("Flush done\n");
2068 }
2069 #endif
2070
2071 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
2072                                   target_ulong value)
2073 {
2074     LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
2075              nr, ul == 0 ? 'u' : 'l', value, env->nip);
2076 }
2077
2078 void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
2079 {
2080     target_ulong mask;
2081
2082     dump_store_bat(env, 'I', 0, nr, value);
2083     if (env->IBAT[0][nr] != value) {
2084         mask = (value << 15) & 0x0FFE0000UL;
2085 #if !defined(FLUSH_ALL_TLBS)
2086         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2087 #endif
2088         /* When storing valid upper BAT, mask BEPI and BRPN
2089          * and invalidate all TLBs covered by this BAT
2090          */
2091         mask = (value << 15) & 0x0FFE0000UL;
2092         env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2093             (value & ~0x0001FFFFUL & ~mask);
2094         env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
2095             (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
2096 #if !defined(FLUSH_ALL_TLBS)
2097         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2098 #else
2099         tlb_flush(env, 1);
2100 #endif
2101     }
2102 }
2103
2104 void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
2105 {
2106     dump_store_bat(env, 'I', 1, nr, value);
2107     env->IBAT[1][nr] = value;
2108 }
2109
2110 void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
2111 {
2112     target_ulong mask;
2113
2114     dump_store_bat(env, 'D', 0, nr, value);
2115     if (env->DBAT[0][nr] != value) {
2116         /* When storing valid upper BAT, mask BEPI and BRPN
2117          * and invalidate all TLBs covered by this BAT
2118          */
2119         mask = (value << 15) & 0x0FFE0000UL;
2120 #if !defined(FLUSH_ALL_TLBS)
2121         do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2122 #endif
2123         mask = (value << 15) & 0x0FFE0000UL;
2124         env->DBAT[0][nr] = (value & 0x00001FFFUL) |
2125             (value & ~0x0001FFFFUL & ~mask);
2126         env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
2127             (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
2128 #if !defined(FLUSH_ALL_TLBS)
2129         do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2130 #else
2131         tlb_flush(env, 1);
2132 #endif
2133     }
2134 }
2135
2136 void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
2137 {
2138     dump_store_bat(env, 'D', 1, nr, value);
2139     env->DBAT[1][nr] = value;
2140 }
2141
2142 void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
2143 {
2144     target_ulong mask;
2145 #if defined(FLUSH_ALL_TLBS)
2146     int do_inval;
2147 #endif
2148
2149     dump_store_bat(env, 'I', 0, nr, value);
2150     if (env->IBAT[0][nr] != value) {
2151 #if defined(FLUSH_ALL_TLBS)
2152         do_inval = 0;
2153 #endif
2154         mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2155         if (env->IBAT[1][nr] & 0x40) {
2156             /* Invalidate BAT only if it is valid */
2157 #if !defined(FLUSH_ALL_TLBS)
2158             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2159 #else
2160             do_inval = 1;
2161 #endif
2162         }
2163         /* When storing valid upper BAT, mask BEPI and BRPN
2164          * and invalidate all TLBs covered by this BAT
2165          */
2166         env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2167             (value & ~0x0001FFFFUL & ~mask);
2168         env->DBAT[0][nr] = env->IBAT[0][nr];
2169         if (env->IBAT[1][nr] & 0x40) {
2170 #if !defined(FLUSH_ALL_TLBS)
2171             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2172 #else
2173             do_inval = 1;
2174 #endif
2175         }
2176 #if defined(FLUSH_ALL_TLBS)
2177         if (do_inval)
2178             tlb_flush(env, 1);
2179 #endif
2180     }
2181 }
2182
2183 void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
2184 {
2185     target_ulong mask;
2186 #if defined(FLUSH_ALL_TLBS)
2187     int do_inval;
2188 #endif
2189
2190     dump_store_bat(env, 'I', 1, nr, value);
2191     if (env->IBAT[1][nr] != value) {
2192 #if defined(FLUSH_ALL_TLBS)
2193         do_inval = 0;
2194 #endif
2195         if (env->IBAT[1][nr] & 0x40) {
2196 #if !defined(FLUSH_ALL_TLBS)
2197             mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2198             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2199 #else
2200             do_inval = 1;
2201 #endif
2202         }
2203         if (value & 0x40) {
2204 #if !defined(FLUSH_ALL_TLBS)
2205             mask = (value << 17) & 0x0FFE0000UL;
2206             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2207 #else
2208             do_inval = 1;
2209 #endif
2210         }
2211         env->IBAT[1][nr] = value;
2212         env->DBAT[1][nr] = value;
2213 #if defined(FLUSH_ALL_TLBS)
2214         if (do_inval)
2215             tlb_flush(env, 1);
2216 #endif
2217     }
2218 }
2219
2220 /*****************************************************************************/
2221 /* TLB management */
2222 void ppc_tlb_invalidate_all (CPUPPCState *env)
2223 {
2224     switch (env->mmu_model) {
2225     case POWERPC_MMU_SOFT_6xx:
2226     case POWERPC_MMU_SOFT_74xx:
2227         ppc6xx_tlb_invalidate_all(env);
2228         break;
2229     case POWERPC_MMU_SOFT_4xx:
2230     case POWERPC_MMU_SOFT_4xx_Z:
2231         ppc4xx_tlb_invalidate_all(env);
2232         break;
2233     case POWERPC_MMU_REAL:
2234         cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2235         break;
2236     case POWERPC_MMU_MPC8xx:
2237         /* XXX: TODO */
2238         cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2239         break;
2240     case POWERPC_MMU_BOOKE:
2241         tlb_flush(env, 1);
2242         break;
2243     case POWERPC_MMU_BOOKE206:
2244         booke206_flush_tlb(env, -1, 0);
2245         break;
2246     case POWERPC_MMU_32B:
2247     case POWERPC_MMU_601:
2248 #if defined(TARGET_PPC64)
2249     case POWERPC_MMU_620:
2250     case POWERPC_MMU_64B:
2251     case POWERPC_MMU_2_06:
2252 #endif /* defined(TARGET_PPC64) */
2253         tlb_flush(env, 1);
2254         break;
2255     default:
2256         /* XXX: TODO */
2257         cpu_abort(env, "Unknown MMU model\n");
2258         break;
2259     }
2260 }
2261
2262 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
2263 {
2264 #if !defined(FLUSH_ALL_TLBS)
2265     addr &= TARGET_PAGE_MASK;
2266     switch (env->mmu_model) {
2267     case POWERPC_MMU_SOFT_6xx:
2268     case POWERPC_MMU_SOFT_74xx:
2269         ppc6xx_tlb_invalidate_virt(env, addr, 0);
2270         if (env->id_tlbs == 1)
2271             ppc6xx_tlb_invalidate_virt(env, addr, 1);
2272         break;
2273     case POWERPC_MMU_SOFT_4xx:
2274     case POWERPC_MMU_SOFT_4xx_Z:
2275         ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
2276         break;
2277     case POWERPC_MMU_REAL:
2278         cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2279         break;
2280     case POWERPC_MMU_MPC8xx:
2281         /* XXX: TODO */
2282         cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2283         break;
2284     case POWERPC_MMU_BOOKE:
2285         /* XXX: TODO */
2286         cpu_abort(env, "BookE MMU model is not implemented\n");
2287         break;
2288     case POWERPC_MMU_BOOKE206:
2289         /* XXX: TODO */
2290         cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
2291         break;
2292     case POWERPC_MMU_32B:
2293     case POWERPC_MMU_601:
2294         /* tlbie invalidate TLBs for all segments */
2295         addr &= ~((target_ulong)-1ULL << 28);
2296         /* XXX: this case should be optimized,
2297          * giving a mask to tlb_flush_page
2298          */
2299         tlb_flush_page(env, addr | (0x0 << 28));
2300         tlb_flush_page(env, addr | (0x1 << 28));
2301         tlb_flush_page(env, addr | (0x2 << 28));
2302         tlb_flush_page(env, addr | (0x3 << 28));
2303         tlb_flush_page(env, addr | (0x4 << 28));
2304         tlb_flush_page(env, addr | (0x5 << 28));
2305         tlb_flush_page(env, addr | (0x6 << 28));
2306         tlb_flush_page(env, addr | (0x7 << 28));
2307         tlb_flush_page(env, addr | (0x8 << 28));
2308         tlb_flush_page(env, addr | (0x9 << 28));
2309         tlb_flush_page(env, addr | (0xA << 28));
2310         tlb_flush_page(env, addr | (0xB << 28));
2311         tlb_flush_page(env, addr | (0xC << 28));
2312         tlb_flush_page(env, addr | (0xD << 28));
2313         tlb_flush_page(env, addr | (0xE << 28));
2314         tlb_flush_page(env, addr | (0xF << 28));
2315         break;
2316 #if defined(TARGET_PPC64)
2317     case POWERPC_MMU_620:
2318     case POWERPC_MMU_64B:
2319     case POWERPC_MMU_2_06:
2320         /* tlbie invalidate TLBs for all segments */
2321         /* XXX: given the fact that there are too many segments to invalidate,
2322          *      and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2323          *      we just invalidate all TLBs
2324          */
2325         tlb_flush(env, 1);
2326         break;
2327 #endif /* defined(TARGET_PPC64) */
2328     default:
2329         /* XXX: TODO */
2330         cpu_abort(env, "Unknown MMU model\n");
2331         break;
2332     }
2333 #else
2334     ppc_tlb_invalidate_all(env);
2335 #endif
2336 }
2337
2338 /*****************************************************************************/
2339 /* Special registers manipulation */
2340 #if defined(TARGET_PPC64)
2341 void ppc_store_asr (CPUPPCState *env, target_ulong value)
2342 {
2343     if (env->asr != value) {
2344         env->asr = value;
2345         tlb_flush(env, 1);
2346     }
2347 }
2348 #endif
2349
2350 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
2351 {
2352     LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
2353     if (env->spr[SPR_SDR1] != value) {
2354         env->spr[SPR_SDR1] = value;
2355 #if defined(TARGET_PPC64)
2356         if (env->mmu_model & POWERPC_MMU_64) {
2357             target_ulong htabsize = value & SDR_64_HTABSIZE;
2358
2359             if (htabsize > 28) {
2360                 fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2361                         " stored in SDR1\n", htabsize);
2362                 htabsize = 28;
2363             }
2364             env->htab_mask = (1ULL << (htabsize + 18)) - 1;
2365             env->htab_base = value & SDR_64_HTABORG;
2366         } else
2367 #endif /* defined(TARGET_PPC64) */
2368         {
2369             /* FIXME: Should check for valid HTABMASK values */
2370             env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
2371             env->htab_base = value & SDR_32_HTABORG;
2372         }
2373         tlb_flush(env, 1);
2374     }
2375 }
2376
2377 #if defined(TARGET_PPC64)
2378 target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
2379 {
2380     // XXX
2381     return 0;
2382 }
2383 #endif
2384
2385 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2386 {
2387     LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2388             srnum, value, env->sr[srnum]);
2389 #if defined(TARGET_PPC64)
2390     if (env->mmu_model & POWERPC_MMU_64) {
2391         uint64_t rb = 0, rs = 0;
2392
2393         /* ESID = srnum */
2394         rb |= ((uint32_t)srnum & 0xf) << 28;
2395         /* Set the valid bit */
2396         rb |= 1 << 27;
2397         /* Index = ESID */
2398         rb |= (uint32_t)srnum;
2399
2400         /* VSID = VSID */
2401         rs |= (value & 0xfffffff) << 12;
2402         /* flags = flags */
2403         rs |= ((value >> 27) & 0xf) << 8;
2404
2405         ppc_store_slb(env, rb, rs);
2406     } else
2407 #endif
2408     if (env->sr[srnum] != value) {
2409         env->sr[srnum] = value;
2410 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2411    flusing the whole TLB. */
2412 #if !defined(FLUSH_ALL_TLBS) && 0
2413         {
2414             target_ulong page, end;
2415             /* Invalidate 256 MB of virtual memory */
2416             page = (16 << 20) * srnum;
2417             end = page + (16 << 20);
2418             for (; page != end; page += TARGET_PAGE_SIZE)
2419                 tlb_flush_page(env, page);
2420         }
2421 #else
2422         tlb_flush(env, 1);
2423 #endif
2424     }
2425 }
2426 #endif /* !defined (CONFIG_USER_ONLY) */
2427
2428 /* GDBstub can read and write MSR... */
2429 void ppc_store_msr (CPUPPCState *env, target_ulong value)
2430 {
2431     hreg_store_msr(env, value, 0);
2432 }
2433
2434 /*****************************************************************************/
2435 /* Exception processing */
2436 #if defined (CONFIG_USER_ONLY)
2437 void do_interrupt (CPUPPCState *env)
2438 {
2439     env->exception_index = POWERPC_EXCP_NONE;
2440     env->error_code = 0;
2441 }
2442
2443 void ppc_hw_interrupt (CPUPPCState *env)
2444 {
2445     env->exception_index = POWERPC_EXCP_NONE;
2446     env->error_code = 0;
2447 }
2448 #else /* defined (CONFIG_USER_ONLY) */
2449 static inline void dump_syscall(CPUPPCState *env)
2450 {
2451     qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2452                   " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2453                   " nip=" TARGET_FMT_lx "\n",
2454                   ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2455                   ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2456                   ppc_dump_gpr(env, 6), env->nip);
2457 }
2458
2459 /* Note that this function should be greatly optimized
2460  * when called with a constant excp, from ppc_hw_interrupt
2461  */
2462 static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp)
2463 {
2464     target_ulong msr, new_msr, vector;
2465     int srr0, srr1, asrr0, asrr1;
2466     int lpes0, lpes1, lev;
2467
2468     if (0) {
2469         /* XXX: find a suitable condition to enable the hypervisor mode */
2470         lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2471         lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2472     } else {
2473         /* Those values ensure we won't enter the hypervisor mode */
2474         lpes0 = 0;
2475         lpes1 = 1;
2476     }
2477
2478     qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2479                   " => %08x (%02x)\n", env->nip, excp, env->error_code);
2480
2481     /* new srr1 value excluding must-be-zero bits */
2482     msr = env->msr & ~0x783f0000ULL;
2483
2484     /* new interrupt handler msr */
2485     new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2486
2487     /* target registers */
2488     srr0 = SPR_SRR0;
2489     srr1 = SPR_SRR1;
2490     asrr0 = -1;
2491     asrr1 = -1;
2492
2493     switch (excp) {
2494     case POWERPC_EXCP_NONE:
2495         /* Should never happen */
2496         return;
2497     case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
2498         switch (excp_model) {
2499         case POWERPC_EXCP_40x:
2500             srr0 = SPR_40x_SRR2;
2501             srr1 = SPR_40x_SRR3;
2502             break;
2503         case POWERPC_EXCP_BOOKE:
2504             srr0 = SPR_BOOKE_CSRR0;
2505             srr1 = SPR_BOOKE_CSRR1;
2506             break;
2507         case POWERPC_EXCP_G2:
2508             break;
2509         default:
2510             goto excp_invalid;
2511         }
2512         goto store_next;
2513     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
2514         if (msr_me == 0) {
2515             /* Machine check exception is not enabled.
2516              * Enter checkstop state.
2517              */
2518             if (qemu_log_enabled()) {
2519                 qemu_log("Machine check while not allowed. "
2520                         "Entering checkstop state\n");
2521             } else {
2522                 fprintf(stderr, "Machine check while not allowed. "
2523                         "Entering checkstop state\n");
2524             }
2525             env->halted = 1;
2526             env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2527         }
2528         if (0) {
2529             /* XXX: find a suitable condition to enable the hypervisor mode */
2530             new_msr |= (target_ulong)MSR_HVB;
2531         }
2532
2533         /* machine check exceptions don't have ME set */
2534         new_msr &= ~((target_ulong)1 << MSR_ME);
2535
2536         /* XXX: should also have something loaded in DAR / DSISR */
2537         switch (excp_model) {
2538         case POWERPC_EXCP_40x:
2539             srr0 = SPR_40x_SRR2;
2540             srr1 = SPR_40x_SRR3;
2541             break;
2542         case POWERPC_EXCP_BOOKE:
2543             srr0 = SPR_BOOKE_MCSRR0;
2544             srr1 = SPR_BOOKE_MCSRR1;
2545             asrr0 = SPR_BOOKE_CSRR0;
2546             asrr1 = SPR_BOOKE_CSRR1;
2547             break;
2548         default:
2549             break;
2550         }
2551         goto store_next;
2552     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
2553         LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2554                  "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2555         if (lpes1 == 0)
2556             new_msr |= (target_ulong)MSR_HVB;
2557         goto store_next;
2558     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
2559         LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2560                  "\n", msr, env->nip);
2561         if (lpes1 == 0)
2562             new_msr |= (target_ulong)MSR_HVB;
2563         msr |= env->error_code;
2564         goto store_next;
2565     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
2566         if (lpes0 == 1)
2567             new_msr |= (target_ulong)MSR_HVB;
2568         goto store_next;
2569     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
2570         if (lpes1 == 0)
2571             new_msr |= (target_ulong)MSR_HVB;
2572         /* XXX: this is false */
2573         /* Get rS/rD and rA from faulting opcode */
2574         env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2575         goto store_current;
2576     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
2577         switch (env->error_code & ~0xF) {
2578         case POWERPC_EXCP_FP:
2579             if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2580                 LOG_EXCP("Ignore floating point exception\n");
2581                 env->exception_index = POWERPC_EXCP_NONE;
2582                 env->error_code = 0;
2583                 return;
2584             }
2585             if (lpes1 == 0)
2586                 new_msr |= (target_ulong)MSR_HVB;
2587             msr |= 0x00100000;
2588             if (msr_fe0 == msr_fe1)
2589                 goto store_next;
2590             msr |= 0x00010000;
2591             break;
2592         case POWERPC_EXCP_INVAL:
2593             LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2594             if (lpes1 == 0)
2595                 new_msr |= (target_ulong)MSR_HVB;
2596             msr |= 0x00080000;
2597             env->spr[SPR_BOOKE_ESR] = ESR_PIL;
2598             break;
2599         case POWERPC_EXCP_PRIV:
2600             if (lpes1 == 0)
2601                 new_msr |= (target_ulong)MSR_HVB;
2602             msr |= 0x00040000;
2603             env->spr[SPR_BOOKE_ESR] = ESR_PPR;
2604             break;
2605         case POWERPC_EXCP_TRAP:
2606             if (lpes1 == 0)
2607                 new_msr |= (target_ulong)MSR_HVB;
2608             msr |= 0x00020000;
2609             env->spr[SPR_BOOKE_ESR] = ESR_PTR;
2610             break;
2611         default:
2612             /* Should never occur */
2613             cpu_abort(env, "Invalid program exception %d. Aborting\n",
2614                       env->error_code);
2615             break;
2616         }
2617         goto store_current;
2618     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
2619         if (lpes1 == 0)
2620             new_msr |= (target_ulong)MSR_HVB;
2621         goto store_current;
2622     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
2623         dump_syscall(env);
2624         lev = env->error_code;
2625         if ((lev == 1) && cpu_ppc_hypercall) {
2626             cpu_ppc_hypercall(env);
2627             return;
2628         }
2629         if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2630             new_msr |= (target_ulong)MSR_HVB;
2631         goto store_next;
2632     case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
2633         goto store_current;
2634     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
2635         if (lpes1 == 0)
2636             new_msr |= (target_ulong)MSR_HVB;
2637         goto store_next;
2638     case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
2639         /* FIT on 4xx */
2640         LOG_EXCP("FIT exception\n");
2641         goto store_next;
2642     case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
2643         LOG_EXCP("WDT exception\n");
2644         switch (excp_model) {
2645         case POWERPC_EXCP_BOOKE:
2646             srr0 = SPR_BOOKE_CSRR0;
2647             srr1 = SPR_BOOKE_CSRR1;
2648             break;
2649         default:
2650             break;
2651         }
2652         goto store_next;
2653     case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
2654         goto store_next;
2655     case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
2656         goto store_next;
2657     case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
2658         switch (excp_model) {
2659         case POWERPC_EXCP_BOOKE:
2660             srr0 = SPR_BOOKE_DSRR0;
2661             srr1 = SPR_BOOKE_DSRR1;
2662             asrr0 = SPR_BOOKE_CSRR0;
2663             asrr1 = SPR_BOOKE_CSRR1;
2664             break;
2665         default:
2666             break;
2667         }
2668         /* XXX: TODO */
2669         cpu_abort(env, "Debug exception is not implemented yet !\n");
2670         goto store_next;
2671     case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
2672         env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2673         goto store_current;
2674     case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
2675         /* XXX: TODO */
2676         cpu_abort(env, "Embedded floating point data exception "
2677                   "is not implemented yet !\n");
2678         env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2679         goto store_next;
2680     case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
2681         /* XXX: TODO */
2682         cpu_abort(env, "Embedded floating point round exception "
2683                   "is not implemented yet !\n");
2684         env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2685         goto store_next;
2686     case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
2687         /* XXX: TODO */
2688         cpu_abort(env,
2689                   "Performance counter exception is not implemented yet !\n");
2690         goto store_next;
2691     case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
2692         goto store_next;
2693     case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
2694         srr0 = SPR_BOOKE_CSRR0;
2695         srr1 = SPR_BOOKE_CSRR1;
2696         goto store_next;
2697     case POWERPC_EXCP_RESET:     /* System reset exception                   */
2698         if (msr_pow) {
2699             /* indicate that we resumed from power save mode */
2700             msr |= 0x10000;
2701         } else {
2702             new_msr &= ~((target_ulong)1 << MSR_ME);
2703         }
2704
2705         if (0) {
2706             /* XXX: find a suitable condition to enable the hypervisor mode */
2707             new_msr |= (target_ulong)MSR_HVB;
2708         }
2709         goto store_next;
2710     case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
2711         if (lpes1 == 0)
2712             new_msr |= (target_ulong)MSR_HVB;
2713         goto store_next;
2714     case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
2715         if (lpes1 == 0)
2716             new_msr |= (target_ulong)MSR_HVB;
2717         goto store_next;
2718     case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
2719         srr0 = SPR_HSRR0;
2720         srr1 = SPR_HSRR1;
2721         new_msr |= (target_ulong)MSR_HVB;
2722         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2723         goto store_next;
2724     case POWERPC_EXCP_TRACE:     /* Trace exception                          */
2725         if (lpes1 == 0)
2726             new_msr |= (target_ulong)MSR_HVB;
2727         goto store_next;
2728     case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
2729         srr0 = SPR_HSRR0;
2730         srr1 = SPR_HSRR1;
2731         new_msr |= (target_ulong)MSR_HVB;
2732         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2733         goto store_next;
2734     case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
2735         srr0 = SPR_HSRR0;
2736         srr1 = SPR_HSRR1;
2737         new_msr |= (target_ulong)MSR_HVB;
2738         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2739         goto store_next;
2740     case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
2741         srr0 = SPR_HSRR0;
2742         srr1 = SPR_HSRR1;
2743         new_msr |= (target_ulong)MSR_HVB;
2744         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2745         goto store_next;
2746     case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
2747         srr0 = SPR_HSRR0;
2748         srr1 = SPR_HSRR1;
2749         new_msr |= (target_ulong)MSR_HVB;
2750         new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2751         goto store_next;
2752     case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
2753         if (lpes1 == 0)
2754             new_msr |= (target_ulong)MSR_HVB;
2755         goto store_current;
2756     case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
2757         LOG_EXCP("PIT exception\n");
2758         goto store_next;
2759     case POWERPC_EXCP_IO:        /* IO error exception                       */
2760         /* XXX: TODO */
2761         cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2762         goto store_next;
2763     case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
2764         /* XXX: TODO */
2765         cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2766         goto store_next;
2767     case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
2768         /* XXX: TODO */
2769         cpu_abort(env, "602 emulation trap exception "
2770                   "is not implemented yet !\n");
2771         goto store_next;
2772     case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
2773         if (lpes1 == 0) /* XXX: check this */
2774             new_msr |= (target_ulong)MSR_HVB;
2775         switch (excp_model) {
2776         case POWERPC_EXCP_602:
2777         case POWERPC_EXCP_603:
2778         case POWERPC_EXCP_603E:
2779         case POWERPC_EXCP_G2:
2780             goto tlb_miss_tgpr;
2781         case POWERPC_EXCP_7x5:
2782             goto tlb_miss;
2783         case POWERPC_EXCP_74xx:
2784             goto tlb_miss_74xx;
2785         default:
2786             cpu_abort(env, "Invalid instruction TLB miss exception\n");
2787             break;
2788         }
2789         break;
2790     case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
2791         if (lpes1 == 0) /* XXX: check this */
2792             new_msr |= (target_ulong)MSR_HVB;
2793         switch (excp_model) {
2794         case POWERPC_EXCP_602:
2795         case POWERPC_EXCP_603:
2796         case POWERPC_EXCP_603E:
2797         case POWERPC_EXCP_G2:
2798             goto tlb_miss_tgpr;
2799         case POWERPC_EXCP_7x5:
2800             goto tlb_miss;
2801         case POWERPC_EXCP_74xx:
2802             goto tlb_miss_74xx;
2803         default:
2804             cpu_abort(env, "Invalid data load TLB miss exception\n");
2805             break;
2806         }
2807         break;
2808     case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
2809         if (lpes1 == 0) /* XXX: check this */
2810             new_msr |= (target_ulong)MSR_HVB;
2811         switch (excp_model) {
2812         case POWERPC_EXCP_602:
2813         case POWERPC_EXCP_603:
2814         case POWERPC_EXCP_603E:
2815         case POWERPC_EXCP_G2:
2816         tlb_miss_tgpr:
2817             /* Swap temporary saved registers with GPRs */
2818             if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2819                 new_msr |= (target_ulong)1 << MSR_TGPR;
2820                 hreg_swap_gpr_tgpr(env);
2821             }
2822             goto tlb_miss;
2823         case POWERPC_EXCP_7x5:
2824         tlb_miss:
2825 #if defined (DEBUG_SOFTWARE_TLB)
2826             if (qemu_log_enabled()) {
2827                 const char *es;
2828                 target_ulong *miss, *cmp;
2829                 int en;
2830                 if (excp == POWERPC_EXCP_IFTLB) {
2831                     es = "I";
2832                     en = 'I';
2833                     miss = &env->spr[SPR_IMISS];
2834                     cmp = &env->spr[SPR_ICMP];
2835                 } else {
2836                     if (excp == POWERPC_EXCP_DLTLB)
2837                         es = "DL";
2838                     else
2839                         es = "DS";
2840                     en = 'D';
2841                     miss = &env->spr[SPR_DMISS];
2842                     cmp = &env->spr[SPR_DCMP];
2843                 }
2844                 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2845                          TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2846                          TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2847                          env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2848                          env->error_code);
2849             }
2850 #endif
2851             msr |= env->crf[0] << 28;
2852             msr |= env->error_code; /* key, D/I, S/L bits */
2853             /* Set way using a LRU mechanism */
2854             msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2855             break;
2856         case POWERPC_EXCP_74xx:
2857         tlb_miss_74xx:
2858 #if defined (DEBUG_SOFTWARE_TLB)
2859             if (qemu_log_enabled()) {
2860                 const char *es;
2861                 target_ulong *miss, *cmp;
2862                 int en;
2863                 if (excp == POWERPC_EXCP_IFTLB) {
2864                     es = "I";
2865                     en = 'I';
2866                     miss = &env->spr[SPR_TLBMISS];
2867                     cmp = &env->spr[SPR_PTEHI];
2868                 } else {
2869                     if (excp == POWERPC_EXCP_DLTLB)
2870                         es = "DL";
2871                     else
2872                         es = "DS";
2873                     en = 'D';
2874                     miss = &env->spr[SPR_TLBMISS];
2875                     cmp = &env->spr[SPR_PTEHI];
2876                 }
2877                 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2878                          TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2879                          env->error_code);
2880             }
2881 #endif
2882             msr |= env->error_code; /* key bit */
2883             break;
2884         default:
2885             cpu_abort(env, "Invalid data store TLB miss exception\n");
2886             break;
2887         }
2888         goto store_next;
2889     case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
2890         /* XXX: TODO */
2891         cpu_abort(env, "Floating point assist exception "
2892                   "is not implemented yet !\n");
2893         goto store_next;
2894     case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
2895         /* XXX: TODO */
2896         cpu_abort(env, "DABR exception is not implemented yet !\n");
2897         goto store_next;
2898     case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
2899         /* XXX: TODO */
2900         cpu_abort(env, "IABR exception is not implemented yet !\n");
2901         goto store_next;
2902     case POWERPC_EXCP_SMI:       /* System management interrupt              */
2903         /* XXX: TODO */
2904         cpu_abort(env, "SMI exception is not implemented yet !\n");
2905         goto store_next;
2906     case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
2907         /* XXX: TODO */
2908         cpu_abort(env, "Thermal management exception "
2909                   "is not implemented yet !\n");
2910         goto store_next;
2911     case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
2912         if (lpes1 == 0)
2913             new_msr |= (target_ulong)MSR_HVB;
2914         /* XXX: TODO */
2915         cpu_abort(env,
2916                   "Performance counter exception is not implemented yet !\n");
2917         goto store_next;
2918     case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
2919         /* XXX: TODO */
2920         cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2921         goto store_next;
2922     case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
2923         /* XXX: TODO */
2924         cpu_abort(env,
2925                   "970 soft-patch exception is not implemented yet !\n");
2926         goto store_next;
2927     case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
2928         /* XXX: TODO */
2929         cpu_abort(env,
2930                   "970 maintenance exception is not implemented yet !\n");
2931         goto store_next;
2932     case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
2933         /* XXX: TODO */
2934         cpu_abort(env, "Maskable external exception "
2935                   "is not implemented yet !\n");
2936         goto store_next;
2937     case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
2938         /* XXX: TODO */
2939         cpu_abort(env, "Non maskable external exception "
2940                   "is not implemented yet !\n");
2941         goto store_next;
2942     default:
2943     excp_invalid:
2944         cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2945         break;
2946     store_current:
2947         /* save current instruction location */
2948         env->spr[srr0] = env->nip - 4;
2949         break;
2950     store_next:
2951         /* save next instruction location */
2952         env->spr[srr0] = env->nip;
2953         break;
2954     }
2955     /* Save MSR */
2956     env->spr[srr1] = msr;
2957     /* If any alternate SRR register are defined, duplicate saved values */
2958     if (asrr0 != -1)
2959         env->spr[asrr0] = env->spr[srr0];
2960     if (asrr1 != -1)
2961         env->spr[asrr1] = env->spr[srr1];
2962     /* If we disactivated any translation, flush TLBs */
2963     if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2964         tlb_flush(env, 1);
2965
2966     if (msr_ile) {
2967         new_msr |= (target_ulong)1 << MSR_LE;
2968     }
2969
2970     /* Jump to handler */
2971     vector = env->excp_vectors[excp];
2972     if (vector == (target_ulong)-1ULL) {
2973         cpu_abort(env, "Raised an exception without defined vector %d\n",
2974                   excp);
2975     }
2976     vector |= env->excp_prefix;
2977 #if defined(TARGET_PPC64)
2978     if (excp_model == POWERPC_EXCP_BOOKE) {
2979         if (!msr_icm) {
2980             vector = (uint32_t)vector;
2981         } else {
2982             new_msr |= (target_ulong)1 << MSR_CM;
2983         }
2984     } else {
2985         if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2986             vector = (uint32_t)vector;
2987         } else {
2988             new_msr |= (target_ulong)1 << MSR_SF;
2989         }
2990     }
2991 #endif
2992     /* XXX: we don't use hreg_store_msr here as already have treated
2993      *      any special case that could occur. Just store MSR and update hflags
2994      */
2995     env->msr = new_msr & env->msr_mask;
2996     hreg_compute_hflags(env);
2997     env->nip = vector;
2998     /* Reset exception state */
2999     env->exception_index = POWERPC_EXCP_NONE;
3000     env->error_code = 0;
3001
3002     if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
3003         (env->mmu_model == POWERPC_MMU_BOOKE206)) {
3004         /* XXX: The BookE changes address space when switching modes,
3005                 we should probably implement that as different MMU indexes,
3006                 but for the moment we do it the slow way and flush all.  */
3007         tlb_flush(env, 1);
3008     }
3009 }
3010
3011 void do_interrupt (CPUPPCState *env)
3012 {
3013     powerpc_excp(env, env->excp_model, env->exception_index);
3014 }
3015
3016 void ppc_hw_interrupt (CPUPPCState *env)
3017 {
3018     int hdice;
3019
3020 #if 0
3021     qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
3022                 __func__, env, env->pending_interrupts,
3023                 env->interrupt_request, (int)msr_me, (int)msr_ee);
3024 #endif
3025     /* External reset */
3026     if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
3027         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
3028         powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
3029         return;
3030     }
3031     /* Machine check exception */
3032     if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
3033         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
3034         powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
3035         return;
3036     }
3037 #if 0 /* TODO */
3038     /* External debug exception */
3039     if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
3040         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
3041         powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
3042         return;
3043     }
3044 #endif
3045     if (0) {
3046         /* XXX: find a suitable condition to enable the hypervisor mode */
3047         hdice = env->spr[SPR_LPCR] & 1;
3048     } else {
3049         hdice = 0;
3050     }
3051     if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
3052         /* Hypervisor decrementer exception */
3053         if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
3054             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
3055             powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
3056             return;
3057         }
3058     }
3059     if (msr_ce != 0) {
3060         /* External critical interrupt */
3061         if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
3062             /* Taking a critical external interrupt does not clear the external
3063              * critical interrupt status
3064              */
3065 #if 0
3066             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
3067 #endif
3068             powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
3069             return;
3070         }
3071     }
3072     if (msr_ee != 0) {
3073         /* Watchdog timer on embedded PowerPC */
3074         if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
3075             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
3076             powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
3077             return;
3078         }
3079         if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
3080             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
3081             powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
3082             return;
3083         }
3084         /* Fixed interval timer on embedded PowerPC */
3085         if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
3086             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
3087             powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
3088             return;
3089         }
3090         /* Programmable interval timer on embedded PowerPC */
3091         if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
3092             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
3093             powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
3094             return;
3095         }
3096         /* Decrementer exception */
3097         if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
3098             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
3099             powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
3100             return;
3101         }
3102         /* External interrupt */
3103         if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
3104             /* Taking an external interrupt does not clear the external
3105              * interrupt status
3106              */
3107 #if 0
3108             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
3109 #endif
3110             powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
3111             return;
3112         }
3113         if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
3114             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
3115             powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
3116             return;
3117         }
3118         if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
3119             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
3120             powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
3121             return;
3122         }
3123         /* Thermal interrupt */
3124         if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
3125             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
3126             powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
3127             return;
3128         }
3129     }
3130 }
3131 #endif /* !CONFIG_USER_ONLY */
3132
3133 void cpu_dump_rfi (target_ulong RA, target_ulong msr)
3134 {
3135     qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
3136              TARGET_FMT_lx "\n", RA, msr);
3137 }
3138
3139 void cpu_state_reset(CPUPPCState *env)
3140 {
3141     target_ulong msr;
3142
3143     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
3144         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
3145         log_cpu_state(env, 0);
3146     }
3147
3148     msr = (target_ulong)0;
3149     if (0) {
3150         /* XXX: find a suitable condition to enable the hypervisor mode */
3151         msr |= (target_ulong)MSR_HVB;
3152     }
3153     msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
3154     msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
3155     msr |= (target_ulong)1 << MSR_EP;
3156 #if defined (DO_SINGLE_STEP) && 0
3157     /* Single step trace mode */
3158     msr |= (target_ulong)1 << MSR_SE;
3159     msr |= (target_ulong)1 << MSR_BE;
3160 #endif
3161 #if defined(CONFIG_USER_ONLY)
3162     msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
3163     msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
3164     msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
3165     msr |= (target_ulong)1 << MSR_PR;
3166 #else
3167     env->excp_prefix = env->hreset_excp_prefix;
3168     env->nip = env->hreset_vector | env->excp_prefix;
3169     if (env->mmu_model != POWERPC_MMU_REAL)
3170         ppc_tlb_invalidate_all(env);
3171 #endif
3172     env->msr = msr & env->msr_mask;
3173 #if defined(TARGET_PPC64)
3174     if (env->mmu_model & POWERPC_MMU_64)
3175         env->msr |= (1ULL << MSR_SF);
3176 #endif
3177     hreg_compute_hflags(env);
3178     env->reserve_addr = (target_ulong)-1ULL;
3179     /* Be sure no exception or interrupt is pending */
3180     env->pending_interrupts = 0;
3181     env->exception_index = POWERPC_EXCP_NONE;
3182     env->error_code = 0;
3183     /* Flush all TLBs */
3184     tlb_flush(env, 1);
3185 }
3186
3187 CPUPPCState *cpu_ppc_init (const char *cpu_model)
3188 {
3189     CPUPPCState *env;
3190     const ppc_def_t *def;
3191
3192     def = cpu_ppc_find_by_name(cpu_model);
3193     if (!def)
3194         return NULL;
3195
3196     env = g_malloc0(sizeof(CPUPPCState));
3197     cpu_exec_init(env);
3198     if (tcg_enabled()) {
3199         ppc_translate_init();
3200     }
3201     /* Adjust cpu index for SMT */
3202 #if !defined(CONFIG_USER_ONLY)
3203     if (kvm_enabled()) {
3204         int smt = kvmppc_smt_threads();
3205
3206         env->cpu_index = (env->cpu_index / smp_threads)*smt
3207             + (env->cpu_index % smp_threads);
3208     }
3209 #endif /* !CONFIG_USER_ONLY */
3210     env->cpu_model_str = cpu_model;
3211     cpu_ppc_register_internal(env, def);
3212
3213     qemu_init_vcpu(env);
3214
3215     return env;
3216 }
3217
3218 void cpu_ppc_close (CPUPPCState *env)
3219 {
3220     /* Should also remove all opcode tables... */
3221     g_free(env);
3222 }
This page took 0.198169 seconds and 4 git commands to generate.