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