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