xref: /qemu/target/ppc/mmu_common.c (revision 6ca35e8763e9c37a9cedd28d286f78fbbf45968c)
1 /*
2  *  PowerPC MMU, TLB, SLB and BAT 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.1 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 
20 #include "qemu/osdep.h"
21 #include "qemu/units.h"
22 #include "cpu.h"
23 #include "sysemu/kvm.h"
24 #include "kvm_ppc.h"
25 #include "mmu-hash64.h"
26 #include "mmu-hash32.h"
27 #include "exec/exec-all.h"
28 #include "exec/page-protection.h"
29 #include "exec/log.h"
30 #include "helper_regs.h"
31 #include "qemu/error-report.h"
32 #include "qemu/qemu-print.h"
33 #include "internal.h"
34 #include "mmu-book3s-v3.h"
35 #include "mmu-radix64.h"
36 #include "mmu-booke.h"
37 
38 /* #define DUMP_PAGE_TABLES */
39 
40 /* Context used internally during MMU translations */
41 typedef struct {
42     hwaddr raddr;      /* Real address             */
43     int prot;          /* Protection bits          */
44 } mmu_ctx_t;
45 
46 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
47 {
48     PowerPCCPU *cpu = env_archcpu(env);
49     qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
50     assert(!cpu->env.has_hv_mode || !cpu->vhyp);
51 #if defined(TARGET_PPC64)
52     if (mmu_is_64bit(env->mmu_model)) {
53         target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
54         target_ulong htabsize = value & SDR_64_HTABSIZE;
55 
56         if (value & ~sdr_mask) {
57             qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx
58                      " set in SDR1", value & ~sdr_mask);
59             value &= sdr_mask;
60         }
61         if (htabsize > 28) {
62             qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx
63                      " stored in SDR1", htabsize);
64             return;
65         }
66     }
67 #endif /* defined(TARGET_PPC64) */
68     /* FIXME: Should check for valid HTABMASK values in 32-bit case */
69     env->spr[SPR_SDR1] = value;
70 }
71 
72 /*****************************************************************************/
73 /* PowerPC MMU emulation */
74 
75 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
76                                     int way, int is_code)
77 {
78     int nr;
79 
80     /* Select TLB num in a way from address */
81     nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
82     /* Select TLB way */
83     nr += env->tlb_per_way * way;
84     /* 6xx has separate TLBs for instructions and data */
85     if (is_code) {
86         nr += env->nb_tlb;
87     }
88 
89     return nr;
90 }
91 
92 /* Software driven TLB helpers */
93 
94 static int ppc6xx_tlb_check(CPUPPCState *env, hwaddr *raddr, int *prot,
95                             target_ulong eaddr, MMUAccessType access_type,
96                             target_ulong ptem, bool key, bool nx)
97 {
98     ppc6xx_tlb_t *tlb;
99     target_ulong *pte1p;
100     int nr, best, way, ret;
101     bool is_code = (access_type == MMU_INST_FETCH);
102 
103     /* Initialize real address with an invalid value */
104     *raddr = (hwaddr)-1ULL;
105     best = -1;
106     ret = -1; /* No TLB found */
107     for (way = 0; way < env->nb_ways; way++) {
108         nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
109         tlb = &env->tlb.tlb6[nr];
110         /* This test "emulates" the PTE index match for hardware TLBs */
111         if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
112             qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx
113                           " " TARGET_FMT_lx "] <> " TARGET_FMT_lx "\n",
114                           nr, env->nb_tlb,
115                           pte_is_valid(tlb->pte0) ? "valid" : "inval",
116                           tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
117             continue;
118         }
119         qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s " TARGET_FMT_lx " <> "
120                       TARGET_FMT_lx " " TARGET_FMT_lx " %c %c\n",
121                       nr, env->nb_tlb,
122                       pte_is_valid(tlb->pte0) ? "valid" : "inval",
123                       tlb->EPN, eaddr, tlb->pte1,
124                       access_type == MMU_DATA_STORE ? 'S' : 'L',
125                       access_type == MMU_INST_FETCH ? 'I' : 'D');
126         /* Check validity and table match */
127         if (!pte_is_valid(tlb->pte0) || ((tlb->pte0 >> 6) & 1) != 0 ||
128             (tlb->pte0 & PTE_PTEM_MASK) != ptem) {
129             continue;
130         }
131         /* all matches should have equal RPN, WIMG & PP */
132         if (*raddr != (hwaddr)-1ULL &&
133             (*raddr & PTE_CHECK_MASK) != (tlb->pte1 & PTE_CHECK_MASK)) {
134             qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
135             /* TLB inconsistency */
136             continue;
137         }
138         /* Keep the matching PTE information */
139         best = nr;
140         *raddr = tlb->pte1;
141         *prot = ppc_hash32_prot(key, tlb->pte1 & HPTE32_R_PP, nx);
142         if (check_prot_access_type(*prot, access_type)) {
143             qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
144             ret = 0;
145             break;
146         } else {
147             qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
148             ret = -2;
149         }
150     }
151     if (best != -1) {
152         qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx
153                       " prot=%01x ret=%d\n",
154                       *raddr & TARGET_PAGE_MASK, *prot, ret);
155         /* Update page flags */
156         pte1p = &env->tlb.tlb6[best].pte1;
157         *pte1p |= 0x00000100; /* Update accessed flag */
158         if (!(*pte1p & 0x00000080)) {
159             if (access_type == MMU_DATA_STORE && ret == 0) {
160                 /* Update changed flag */
161                 *pte1p |= 0x00000080;
162             } else {
163                 /* Force page fault for first write access */
164                 *prot &= ~PAGE_WRITE;
165             }
166         }
167     }
168     if (ret == -1) {
169         int r = is_code ? SPR_ICMP : SPR_DCMP;
170         env->spr[r] = ptem;
171     }
172 #if defined(DUMP_PAGE_TABLES)
173     if (qemu_loglevel_mask(CPU_LOG_MMU)) {
174         CPUState *cs = env_cpu(env);
175         hwaddr base = ppc_hash32_hpt_base(env_archcpu(env));
176         hwaddr len = ppc_hash32_hpt_mask(env_archcpu(env)) + 0x80;
177         uint32_t a0, a1, a2, a3;
178 
179         qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n",
180                  base, len);
181         for (hwaddr curaddr = base; curaddr < base + len; curaddr += 16) {
182             a0 = ldl_phys(cs->as, curaddr);
183             a1 = ldl_phys(cs->as, curaddr + 4);
184             a2 = ldl_phys(cs->as, curaddr + 8);
185             a3 = ldl_phys(cs->as, curaddr + 12);
186             if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
187                 qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
188                          curaddr, a0, a1, a2, a3);
189             }
190         }
191     }
192 #endif
193     return ret;
194 }
195 
196 /* Perform BAT hit & translation */
197 static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
198                                  int *validp, int *protp, target_ulong *BATu,
199                                  target_ulong *BATl)
200 {
201     target_ulong bl;
202     int pp, valid, prot;
203 
204     bl = (*BATu & BATU32_BL) << 15;
205     valid = 0;
206     prot = 0;
207     if ((!FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000002)) ||
208         (FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000001))) {
209         valid = 1;
210         pp = *BATl & 0x00000003;
211         if (pp != 0) {
212             prot = PAGE_READ | PAGE_EXEC;
213             if (pp == 0x2) {
214                 prot |= PAGE_WRITE;
215             }
216         }
217     }
218     *blp = bl;
219     *validp = valid;
220     *protp = prot;
221 }
222 
223 static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
224                            target_ulong eaddr, MMUAccessType access_type)
225 {
226     target_ulong *BATlt, *BATut, *BATu, *BATl;
227     target_ulong BEPIl, BEPIu, bl;
228     int i, valid, prot;
229     int ret = -1;
230     bool ifetch = access_type == MMU_INST_FETCH;
231 
232     qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
233                   ifetch ? 'I' : 'D', eaddr);
234     if (ifetch) {
235         BATlt = env->IBAT[1];
236         BATut = env->IBAT[0];
237     } else {
238         BATlt = env->DBAT[1];
239         BATut = env->DBAT[0];
240     }
241     for (i = 0; i < env->nb_BATs; i++) {
242         BATu = &BATut[i];
243         BATl = &BATlt[i];
244         BEPIu = *BATu & BATU32_BEPIU;
245         BEPIl = *BATu & BATU32_BEPIL;
246         bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
247         qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
248                       TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
249                       ifetch ? 'I' : 'D', i, eaddr, *BATu, *BATl);
250         if ((eaddr & BATU32_BEPIU) == BEPIu &&
251             ((eaddr & BATU32_BEPIL) & ~bl) == BEPIl) {
252             /* BAT matches */
253             if (valid != 0) {
254                 /* Get physical address */
255                 ctx->raddr = (*BATl & BATU32_BEPIU) |
256                     ((eaddr & BATU32_BEPIL & bl) | (*BATl & BATU32_BEPIL)) |
257                     (eaddr & 0x0001F000);
258                 /* Compute access rights */
259                 ctx->prot = prot;
260                 if (check_prot_access_type(ctx->prot, access_type)) {
261                     qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " HWADDR_FMT_plx
262                                   " prot=%c%c\n", i, ctx->raddr,
263                                   ctx->prot & PAGE_READ ? 'R' : '-',
264                                   ctx->prot & PAGE_WRITE ? 'W' : '-');
265                     ret = 0;
266                 } else {
267                     ret = -2;
268                 }
269                 break;
270             }
271         }
272     }
273     if (ret < 0) {
274         if (qemu_log_enabled()) {
275             qemu_log_mask(CPU_LOG_MMU, "no BAT match for "
276                           TARGET_FMT_lx ":\n", eaddr);
277             for (i = 0; i < 4; i++) {
278                 BATu = &BATut[i];
279                 BATl = &BATlt[i];
280                 BEPIu = *BATu & BATU32_BEPIU;
281                 BEPIl = *BATu & BATU32_BEPIL;
282                 bl = (*BATu & BATU32_BL) << 15;
283                 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx
284                               " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx
285                               "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " "
286                               TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D',
287                               i, eaddr, *BATu, *BATl, BEPIu, BEPIl, bl);
288             }
289         }
290     }
291     /* No hit */
292     return ret;
293 }
294 
295 static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
296                                        target_ulong eaddr,
297                                        hwaddr *hashp, bool *keyp,
298                                        MMUAccessType access_type, int type)
299 {
300     PowerPCCPU *cpu = env_archcpu(env);
301     hwaddr hash;
302     target_ulong vsid, sr, pgidx, ptem;
303     bool key, pr, ds, nx;
304 
305     /* First try to find a BAT entry if there are any */
306     if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) {
307         return 0;
308     }
309 
310     /* Perform segment based translation when no BATs matched */
311     pr = FIELD_EX64(env->msr, MSR, PR);
312 
313     sr = env->sr[eaddr >> 28];
314     key = ppc_hash32_key(pr, sr);
315     *keyp = key;
316     ds = sr & SR32_T;
317     nx = sr & SR32_NX;
318     vsid = sr & SR32_VSID;
319     qemu_log_mask(CPU_LOG_MMU,
320                   "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
321                   " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
322                   " ir=%d dr=%d pr=%d %d t=%d\n",
323                   eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr,
324                   (int)FIELD_EX64(env->msr, MSR, IR),
325                   (int)FIELD_EX64(env->msr, MSR, DR), pr ? 1 : 0,
326                   access_type == MMU_DATA_STORE, type);
327     pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS;
328     hash = vsid ^ pgidx;
329     ptem = (vsid << 7) | (pgidx >> 10); /* Virtual segment ID | API */
330 
331     qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid "
332                   TARGET_FMT_lx "\n", key, ds, nx, vsid);
333     if (!ds) {
334         /* Check if instruction fetch is allowed, if needed */
335         if (type == ACCESS_CODE && nx) {
336             qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
337             return -3;
338         }
339         /* Page address translation */
340         qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
341                       HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
342                       ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
343         *hashp = hash;
344 
345         /* Software TLB search */
346         return ppc6xx_tlb_check(env, &ctx->raddr, &ctx->prot, eaddr,
347                                 access_type, ptem, key, nx);
348     }
349 
350     /* Direct-store segment : absolutely *BUGGY* for now */
351     qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
352     switch (type) {
353     case ACCESS_INT:
354         /* Integer load/store : only access allowed */
355         break;
356     case ACCESS_CACHE:
357         /*
358          * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
359          *
360          * Should make the instruction do no-op.  As it already do
361          * no-op, it's quite easy :-)
362          */
363         ctx->raddr = eaddr;
364         return 0;
365     case ACCESS_CODE: /* No code fetch is allowed in direct-store areas */
366     case ACCESS_FLOAT: /* Floating point load/store */
367     case ACCESS_RES: /* lwarx, ldarx or srwcx. */
368     case ACCESS_EXT: /* eciwx or ecowx */
369         return -4;
370     }
371     if ((access_type == MMU_DATA_STORE || !key) &&
372         (access_type == MMU_DATA_LOAD || key)) {
373         ctx->raddr = eaddr;
374         return 2;
375     }
376     return -2;
377 }
378 
379 static const char *book3e_tsize_to_str[32] = {
380     "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
381     "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
382     "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
383     "1T", "2T"
384 };
385 
386 static void mmubooke_dump_mmu(CPUPPCState *env)
387 {
388     ppcemb_tlb_t *entry;
389     int i;
390 
391 #ifdef CONFIG_KVM
392     if (kvm_enabled() && !env->kvm_sw_tlb) {
393         qemu_printf("Cannot access KVM TLB\n");
394         return;
395     }
396 #endif
397 
398     qemu_printf("\nTLB:\n");
399     qemu_printf("Effective          Physical           Size PID   Prot     "
400                 "Attr\n");
401 
402     entry = &env->tlb.tlbe[0];
403     for (i = 0; i < env->nb_tlb; i++, entry++) {
404         hwaddr ea, pa;
405         target_ulong mask;
406         uint64_t size = (uint64_t)entry->size;
407         char size_buf[20];
408 
409         /* Check valid flag */
410         if (!(entry->prot & PAGE_VALID)) {
411             continue;
412         }
413 
414         mask = ~(entry->size - 1);
415         ea = entry->EPN & mask;
416         pa = entry->RPN & mask;
417         /* Extend the physical address to 36 bits */
418         pa |= (hwaddr)(entry->RPN & 0xF) << 32;
419         if (size >= 1 * MiB) {
420             snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB);
421         } else {
422             snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB);
423         }
424         qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
425                     (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
426                     entry->prot, entry->attr);
427     }
428 
429 }
430 
431 static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset,
432                                      int tlbsize)
433 {
434     ppcmas_tlb_t *entry;
435     int i;
436 
437     qemu_printf("\nTLB%d:\n", tlbn);
438     qemu_printf("Effective          Physical           Size TID   TS SRWX"
439                 " URWX WIMGE U0123\n");
440 
441     entry = &env->tlb.tlbm[offset];
442     for (i = 0; i < tlbsize; i++, entry++) {
443         hwaddr ea, pa, size;
444         int tsize;
445 
446         if (!(entry->mas1 & MAS1_VALID)) {
447             continue;
448         }
449 
450         tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
451         size = 1024ULL << tsize;
452         ea = entry->mas2 & ~(size - 1);
453         pa = entry->mas7_3 & ~(size - 1);
454 
455         qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u  S%c%c%c"
456                     " U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
457                     (uint64_t)ea, (uint64_t)pa,
458                     book3e_tsize_to_str[tsize],
459                     (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
460                     (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
461                     entry->mas7_3 & MAS3_SR ? 'R' : '-',
462                     entry->mas7_3 & MAS3_SW ? 'W' : '-',
463                     entry->mas7_3 & MAS3_SX ? 'X' : '-',
464                     entry->mas7_3 & MAS3_UR ? 'R' : '-',
465                     entry->mas7_3 & MAS3_UW ? 'W' : '-',
466                     entry->mas7_3 & MAS3_UX ? 'X' : '-',
467                     entry->mas2 & MAS2_W ? 'W' : '-',
468                     entry->mas2 & MAS2_I ? 'I' : '-',
469                     entry->mas2 & MAS2_M ? 'M' : '-',
470                     entry->mas2 & MAS2_G ? 'G' : '-',
471                     entry->mas2 & MAS2_E ? 'E' : '-',
472                     entry->mas7_3 & MAS3_U0 ? '0' : '-',
473                     entry->mas7_3 & MAS3_U1 ? '1' : '-',
474                     entry->mas7_3 & MAS3_U2 ? '2' : '-',
475                     entry->mas7_3 & MAS3_U3 ? '3' : '-');
476     }
477 }
478 
479 static void mmubooke206_dump_mmu(CPUPPCState *env)
480 {
481     int offset = 0;
482     int i;
483 
484 #ifdef CONFIG_KVM
485     if (kvm_enabled() && !env->kvm_sw_tlb) {
486         qemu_printf("Cannot access KVM TLB\n");
487         return;
488     }
489 #endif
490 
491     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
492         int size = booke206_tlb_size(env, i);
493 
494         if (size == 0) {
495             continue;
496         }
497 
498         mmubooke206_dump_one_tlb(env, i, offset, size);
499         offset += size;
500     }
501 }
502 
503 static void mmu6xx_dump_BATs(CPUPPCState *env, int type)
504 {
505     target_ulong *BATlt, *BATut, *BATu, *BATl;
506     target_ulong BEPIl, BEPIu, bl;
507     int i;
508 
509     switch (type) {
510     case ACCESS_CODE:
511         BATlt = env->IBAT[1];
512         BATut = env->IBAT[0];
513         break;
514     default:
515         BATlt = env->DBAT[1];
516         BATut = env->DBAT[0];
517         break;
518     }
519 
520     for (i = 0; i < env->nb_BATs; i++) {
521         BATu = &BATut[i];
522         BATl = &BATlt[i];
523         BEPIu = *BATu & BATU32_BEPIU;
524         BEPIl = *BATu & BATU32_BEPIL;
525         bl = (*BATu & BATU32_BL) << 15;
526         qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
527                     " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
528                     TARGET_FMT_lx " " TARGET_FMT_lx "\n",
529                     type == ACCESS_CODE ? "code" : "data", i,
530                     *BATu, *BATl, BEPIu, BEPIl, bl);
531     }
532 }
533 
534 static void mmu6xx_dump_mmu(CPUPPCState *env)
535 {
536     PowerPCCPU *cpu = env_archcpu(env);
537     ppc6xx_tlb_t *tlb;
538     target_ulong sr;
539     int type, way, entry, i;
540 
541     qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu));
542     qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu));
543 
544     qemu_printf("\nSegment registers:\n");
545     for (i = 0; i < 32; i++) {
546         sr = env->sr[i];
547         if (sr & 0x80000000) {
548             qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
549                         "CNTLR_SPEC=0x%05x\n", i,
550                         sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
551                         sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF),
552                         (uint32_t)(sr & 0xFFFFF));
553         } else {
554             qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i,
555                         sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
556                         sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0,
557                         (uint32_t)(sr & 0x00FFFFFF));
558         }
559     }
560 
561     qemu_printf("\nBATs:\n");
562     mmu6xx_dump_BATs(env, ACCESS_INT);
563     mmu6xx_dump_BATs(env, ACCESS_CODE);
564 
565     qemu_printf("\nTLBs                       [EPN    EPN + SIZE]\n");
566     for (type = 0; type < 2; type++) {
567         for (way = 0; way < env->nb_ways; way++) {
568             for (entry = env->nb_tlb * type + env->tlb_per_way * way;
569                  entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1));
570                  entry++) {
571 
572                 tlb = &env->tlb.tlb6[entry];
573                 qemu_printf("%s TLB %02d/%02d way:%d %s ["
574                             TARGET_FMT_lx " " TARGET_FMT_lx "]\n",
575                             type ? "code" : "data", entry % env->nb_tlb,
576                             env->nb_tlb, way,
577                             pte_is_valid(tlb->pte0) ? "valid" : "inval",
578                             tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE);
579             }
580         }
581     }
582 }
583 
584 void dump_mmu(CPUPPCState *env)
585 {
586     switch (env->mmu_model) {
587     case POWERPC_MMU_BOOKE:
588         mmubooke_dump_mmu(env);
589         break;
590     case POWERPC_MMU_BOOKE206:
591         mmubooke206_dump_mmu(env);
592         break;
593     case POWERPC_MMU_SOFT_6xx:
594         mmu6xx_dump_mmu(env);
595         break;
596 #if defined(TARGET_PPC64)
597     case POWERPC_MMU_64B:
598     case POWERPC_MMU_2_03:
599     case POWERPC_MMU_2_06:
600     case POWERPC_MMU_2_07:
601         dump_slb(env_archcpu(env));
602         break;
603     case POWERPC_MMU_3_00:
604         if (ppc64_v3_radix(env_archcpu(env))) {
605             qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n",
606                           __func__);
607         } else {
608             dump_slb(env_archcpu(env));
609         }
610         break;
611 #endif
612     default:
613         qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
614     }
615 }
616 
617 
618 static bool ppc_real_mode_xlate(PowerPCCPU *cpu, vaddr eaddr,
619                                 MMUAccessType access_type,
620                                 hwaddr *raddrp, int *psizep, int *protp)
621 {
622     CPUPPCState *env = &cpu->env;
623 
624     if (access_type == MMU_INST_FETCH ? !FIELD_EX64(env->msr, MSR, IR)
625                                       : !FIELD_EX64(env->msr, MSR, DR)) {
626         *raddrp = eaddr;
627         *protp = PAGE_RWX;
628         *psizep = TARGET_PAGE_BITS;
629         return true;
630     } else if (env->mmu_model == POWERPC_MMU_REAL) {
631         cpu_abort(CPU(cpu), "PowerPC in real mode shold not do translation\n");
632     }
633     return false;
634 }
635 
636 static bool ppc_40x_xlate(PowerPCCPU *cpu, vaddr eaddr,
637                           MMUAccessType access_type,
638                           hwaddr *raddrp, int *psizep, int *protp,
639                           int mmu_idx, bool guest_visible)
640 {
641     CPUState *cs = CPU(cpu);
642     CPUPPCState *env = &cpu->env;
643     int ret;
644 
645     if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
646         return true;
647     }
648 
649     ret = mmu40x_get_physical_address(env, raddrp, protp, eaddr, access_type);
650     if (ret == 0) {
651         *psizep = TARGET_PAGE_BITS;
652         return true;
653     } else if (!guest_visible) {
654         return false;
655     }
656 
657     log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
658     if (access_type == MMU_INST_FETCH) {
659         switch (ret) {
660         case -1:
661             /* No matches in page tables or TLB */
662             cs->exception_index = POWERPC_EXCP_ITLB;
663             env->error_code = 0;
664             env->spr[SPR_40x_DEAR] = eaddr;
665             env->spr[SPR_40x_ESR] = 0x00000000;
666             break;
667         case -2:
668             /* Access rights violation */
669             cs->exception_index = POWERPC_EXCP_ISI;
670             env->error_code = 0x08000000;
671             break;
672         default:
673             g_assert_not_reached();
674         }
675     } else {
676         switch (ret) {
677         case -1:
678             /* No matches in page tables or TLB */
679             cs->exception_index = POWERPC_EXCP_DTLB;
680             env->error_code = 0;
681             env->spr[SPR_40x_DEAR] = eaddr;
682             if (access_type == MMU_DATA_STORE) {
683                 env->spr[SPR_40x_ESR] = 0x00800000;
684             } else {
685                 env->spr[SPR_40x_ESR] = 0x00000000;
686             }
687             break;
688         case -2:
689             /* Access rights violation */
690             cs->exception_index = POWERPC_EXCP_DSI;
691             env->error_code = 0;
692             env->spr[SPR_40x_DEAR] = eaddr;
693             if (access_type == MMU_DATA_STORE) {
694                 env->spr[SPR_40x_ESR] |= 0x00800000;
695             }
696             break;
697         default:
698             g_assert_not_reached();
699         }
700     }
701     return false;
702 }
703 
704 static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
705                           MMUAccessType access_type,
706                           hwaddr *raddrp, int *psizep, int *protp,
707                           int mmu_idx, bool guest_visible)
708 {
709     CPUState *cs = CPU(cpu);
710     CPUPPCState *env = &cpu->env;
711     mmu_ctx_t ctx;
712     hwaddr hash = 0; /* init to 0 to avoid used uninit warning */
713     bool key;
714     int type, ret;
715 
716     if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
717         return true;
718     }
719 
720     if (access_type == MMU_INST_FETCH) {
721         /* code access */
722         type = ACCESS_CODE;
723     } else if (guest_visible) {
724         /* data access */
725         type = env->access_type;
726     } else {
727         type = ACCESS_INT;
728     }
729 
730     ctx.prot = 0;
731     ret = mmu6xx_get_physical_address(env, &ctx, eaddr, &hash, &key,
732                                       access_type, type);
733     if (ret == 0) {
734         *raddrp = ctx.raddr;
735         *protp = ctx.prot;
736         *psizep = TARGET_PAGE_BITS;
737         return true;
738     } else if (!guest_visible) {
739         return false;
740     }
741 
742     log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
743     if (type == ACCESS_CODE) {
744         switch (ret) {
745         case -1:
746             /* No matches in page tables or TLB */
747             cs->exception_index = POWERPC_EXCP_IFTLB;
748             env->error_code = 1 << 18;
749             env->spr[SPR_IMISS] = eaddr;
750             env->spr[SPR_ICMP] |= 0x80000000;
751             goto tlb_miss;
752         case -2:
753             /* Access rights violation */
754             cs->exception_index = POWERPC_EXCP_ISI;
755             env->error_code = 0x08000000;
756             break;
757         case -3:
758             /* No execute protection violation */
759             cs->exception_index = POWERPC_EXCP_ISI;
760             env->error_code = 0x10000000;
761             break;
762         case -4:
763             /* Direct store exception */
764             /* No code fetch is allowed in direct-store areas */
765             cs->exception_index = POWERPC_EXCP_ISI;
766             env->error_code = 0x10000000;
767             break;
768         }
769     } else {
770         switch (ret) {
771         case -1:
772             /* No matches in page tables or TLB */
773             if (access_type == MMU_DATA_STORE) {
774                 cs->exception_index = POWERPC_EXCP_DSTLB;
775                 env->error_code = 1 << 16;
776             } else {
777                 cs->exception_index = POWERPC_EXCP_DLTLB;
778                 env->error_code = 0;
779             }
780             env->spr[SPR_DMISS] = eaddr;
781             env->spr[SPR_DCMP] |= 0x80000000;
782 tlb_miss:
783             env->error_code |= key << 19;
784             env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
785                                   get_pteg_offset32(cpu, hash);
786             env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
787                                   get_pteg_offset32(cpu, ~hash);
788             break;
789         case -2:
790             /* Access rights violation */
791             cs->exception_index = POWERPC_EXCP_DSI;
792             env->error_code = 0;
793             env->spr[SPR_DAR] = eaddr;
794             if (access_type == MMU_DATA_STORE) {
795                 env->spr[SPR_DSISR] = 0x0A000000;
796             } else {
797                 env->spr[SPR_DSISR] = 0x08000000;
798             }
799             break;
800         case -4:
801             /* Direct store exception */
802             switch (type) {
803             case ACCESS_FLOAT:
804                 /* Floating point load/store */
805                 cs->exception_index = POWERPC_EXCP_ALIGN;
806                 env->error_code = POWERPC_EXCP_ALIGN_FP;
807                 env->spr[SPR_DAR] = eaddr;
808                 break;
809             case ACCESS_RES:
810                 /* lwarx, ldarx or stwcx. */
811                 cs->exception_index = POWERPC_EXCP_DSI;
812                 env->error_code = 0;
813                 env->spr[SPR_DAR] = eaddr;
814                 if (access_type == MMU_DATA_STORE) {
815                     env->spr[SPR_DSISR] = 0x06000000;
816                 } else {
817                     env->spr[SPR_DSISR] = 0x04000000;
818                 }
819                 break;
820             case ACCESS_EXT:
821                 /* eciwx or ecowx */
822                 cs->exception_index = POWERPC_EXCP_DSI;
823                 env->error_code = 0;
824                 env->spr[SPR_DAR] = eaddr;
825                 if (access_type == MMU_DATA_STORE) {
826                     env->spr[SPR_DSISR] = 0x06100000;
827                 } else {
828                     env->spr[SPR_DSISR] = 0x04100000;
829                 }
830                 break;
831             default:
832                 printf("DSI: invalid exception (%d)\n", ret);
833                 cs->exception_index = POWERPC_EXCP_PROGRAM;
834                 env->error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
835                 env->spr[SPR_DAR] = eaddr;
836                 break;
837             }
838             break;
839         }
840     }
841     return false;
842 }
843 
844 /*****************************************************************************/
845 
846 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
847                       hwaddr *raddrp, int *psizep, int *protp,
848                       int mmu_idx, bool guest_visible)
849 {
850     switch (cpu->env.mmu_model) {
851 #if defined(TARGET_PPC64)
852     case POWERPC_MMU_3_00:
853         if (ppc64_v3_radix(cpu)) {
854             return ppc_radix64_xlate(cpu, eaddr, access_type, raddrp,
855                                      psizep, protp, mmu_idx, guest_visible);
856         }
857         /* fall through */
858     case POWERPC_MMU_64B:
859     case POWERPC_MMU_2_03:
860     case POWERPC_MMU_2_06:
861     case POWERPC_MMU_2_07:
862         return ppc_hash64_xlate(cpu, eaddr, access_type,
863                                 raddrp, psizep, protp, mmu_idx, guest_visible);
864 #endif
865 
866     case POWERPC_MMU_32B:
867         return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp,
868                                psizep, protp, mmu_idx, guest_visible);
869     case POWERPC_MMU_BOOKE:
870     case POWERPC_MMU_BOOKE206:
871         return ppc_booke_xlate(cpu, eaddr, access_type, raddrp,
872                                psizep, protp, mmu_idx, guest_visible);
873     case POWERPC_MMU_SOFT_4xx:
874         return ppc_40x_xlate(cpu, eaddr, access_type, raddrp,
875                              psizep, protp, mmu_idx, guest_visible);
876     case POWERPC_MMU_SOFT_6xx:
877         return ppc_6xx_xlate(cpu, eaddr, access_type, raddrp,
878                              psizep, protp, mmu_idx, guest_visible);
879     case POWERPC_MMU_REAL:
880         return ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep,
881                                    protp);
882     case POWERPC_MMU_MPC8xx:
883         cpu_abort(env_cpu(&cpu->env), "MPC8xx MMU model is not implemented\n");
884     default:
885         cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n");
886     }
887 }
888 
889 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
890 {
891     PowerPCCPU *cpu = POWERPC_CPU(cs);
892     hwaddr raddr;
893     int s, p;
894 
895     /*
896      * Some MMUs have separate TLBs for code and data. If we only
897      * try an MMU_DATA_LOAD, we may not be able to read instructions
898      * mapped by code TLBs, so we also try a MMU_INST_FETCH.
899      */
900     if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p,
901                   ppc_env_mmu_index(&cpu->env, false), false) ||
902         ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p,
903                   ppc_env_mmu_index(&cpu->env, true), false)) {
904         return raddr & TARGET_PAGE_MASK;
905     }
906     return -1;
907 }
908