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