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