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