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
ppc_store_sdr1(CPUPPCState * env,target_ulong value)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
ppc6xx_tlb_getnum(CPUPPCState * env,target_ulong eaddr,int way,int is_code)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
ppc6xx_tlb_check(CPUPPCState * env,hwaddr * raddr,int * prot,target_ulong eaddr,MMUAccessType access_type,target_ulong ptem,bool key,bool nx)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
get_bat_6xx_tlb(CPUPPCState * env,hwaddr * raddr,int * prot,target_ulong eaddr,MMUAccessType access_type,bool pr)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
mmu6xx_get_physical_address(CPUPPCState * env,hwaddr * raddr,int * prot,target_ulong eaddr,hwaddr * hashp,bool * keyp,MMUAccessType access_type,int type)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
mmubooke_dump_mmu(CPUPPCState * env)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
mmubooke206_dump_one_tlb(CPUPPCState * env,int tlbn,int offset,int tlbsize)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
mmubooke206_dump_mmu(CPUPPCState * env)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
mmu6xx_dump_BATs(CPUPPCState * env,int type)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
mmu6xx_dump_mmu(CPUPPCState * env)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
dump_mmu(CPUPPCState * env)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
ppc_real_mode_xlate(PowerPCCPU * cpu,vaddr eaddr,MMUAccessType access_type,hwaddr * raddrp,int * psizep,int * protp)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
ppc_40x_xlate(PowerPCCPU * cpu,vaddr eaddr,MMUAccessType access_type,hwaddr * raddrp,int * psizep,int * protp,int mmu_idx,bool guest_visible)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
ppc_6xx_xlate(PowerPCCPU * cpu,vaddr eaddr,MMUAccessType access_type,hwaddr * raddrp,int * psizep,int * protp,int mmu_idx,bool guest_visible)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
ppc_xlate(PowerPCCPU * cpu,vaddr eaddr,MMUAccessType access_type,hwaddr * raddrp,int * psizep,int * protp,int mmu_idx,bool guest_visible)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
ppc_cpu_get_phys_page_debug(CPUState * cs,vaddr addr)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