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