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