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