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