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