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