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