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