target/ppc: Change ppcemb_tlb_check() to return bool
[qemu/armbru.git] / target / ppc / mmu_common.c
blobbd7d7d5257ab5d850394e78a49ab29b4fa9de48d
1 /*
2 * PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
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.
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.
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/>.
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/log.h"
29 #include "helper_regs.h"
30 #include "qemu/error-report.h"
31 #include "qemu/main-loop.h"
32 #include "qemu/qemu-print.h"
33 #include "internal.h"
34 #include "mmu-book3s-v3.h"
35 #include "mmu-radix64.h"
37 /* #define DUMP_PAGE_TABLES */
39 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
41 PowerPCCPU *cpu = env_archcpu(env);
42 qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
43 assert(!cpu->env.has_hv_mode || !cpu->vhyp);
44 #if defined(TARGET_PPC64)
45 if (mmu_is_64bit(env->mmu_model)) {
46 target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
47 target_ulong htabsize = value & SDR_64_HTABSIZE;
49 if (value & ~sdr_mask) {
50 qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx
51 " set in SDR1", value & ~sdr_mask);
52 value &= sdr_mask;
54 if (htabsize > 28) {
55 qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx
56 " stored in SDR1", htabsize);
57 return;
60 #endif /* defined(TARGET_PPC64) */
61 /* FIXME: Should check for valid HTABMASK values in 32-bit case */
62 env->spr[SPR_SDR1] = value;
65 /*****************************************************************************/
66 /* PowerPC MMU emulation */
68 static int pp_check(int key, int pp, int nx)
70 int access;
72 /* Compute access rights */
73 access = 0;
74 if (key == 0) {
75 switch (pp) {
76 case 0x0:
77 case 0x1:
78 case 0x2:
79 access |= PAGE_WRITE;
80 /* fall through */
81 case 0x3:
82 access |= PAGE_READ;
83 break;
85 } else {
86 switch (pp) {
87 case 0x0:
88 access = 0;
89 break;
90 case 0x1:
91 case 0x3:
92 access = PAGE_READ;
93 break;
94 case 0x2:
95 access = PAGE_READ | PAGE_WRITE;
96 break;
99 if (nx == 0) {
100 access |= PAGE_EXEC;
103 return access;
106 static int check_prot(int prot, MMUAccessType access_type)
108 return prot & prot_for_access_type(access_type) ? 0 : -2;
111 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
112 int way, int is_code)
114 int nr;
116 /* Select TLB num in a way from address */
117 nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
118 /* Select TLB way */
119 nr += env->tlb_per_way * way;
120 /* 6xx have separate TLBs for instructions and data */
121 if (is_code && env->id_tlbs == 1) {
122 nr += env->nb_tlb;
125 return nr;
128 static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
129 target_ulong pte1, int h,
130 MMUAccessType access_type)
132 target_ulong ptem, mmask;
133 int access, ret, pteh, ptev, pp;
135 ret = -1;
136 /* Check validity and table match */
137 ptev = pte_is_valid(pte0);
138 pteh = (pte0 >> 6) & 1;
139 if (ptev && h == pteh) {
140 /* Check vsid & api */
141 ptem = pte0 & PTE_PTEM_MASK;
142 mmask = PTE_CHECK_MASK;
143 pp = pte1 & 0x00000003;
144 if (ptem == ctx->ptem) {
145 if (ctx->raddr != (hwaddr)-1ULL) {
146 /* all matches should have equal RPN, WIMG & PP */
147 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
148 qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
149 return -3;
152 /* Compute access rights */
153 access = pp_check(ctx->key, pp, ctx->nx);
154 /* Keep the matching PTE information */
155 ctx->raddr = pte1;
156 ctx->prot = access;
157 ret = check_prot(ctx->prot, access_type);
158 if (ret == 0) {
159 /* Access granted */
160 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
161 } else {
162 /* Access right violation */
163 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
168 return ret;
171 static int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
172 int ret, MMUAccessType access_type)
174 int store = 0;
176 /* Update page flags */
177 if (!(*pte1p & 0x00000100)) {
178 /* Update accessed flag */
179 *pte1p |= 0x00000100;
180 store = 1;
182 if (!(*pte1p & 0x00000080)) {
183 if (access_type == MMU_DATA_STORE && ret == 0) {
184 /* Update changed flag */
185 *pte1p |= 0x00000080;
186 store = 1;
187 } else {
188 /* Force page fault for first write access */
189 ctx->prot &= ~PAGE_WRITE;
193 return store;
196 /* Software driven TLB helpers */
198 static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
199 target_ulong eaddr, MMUAccessType access_type)
201 ppc6xx_tlb_t *tlb;
202 int nr, best, way;
203 int ret;
205 best = -1;
206 ret = -1; /* No TLB found */
207 for (way = 0; way < env->nb_ways; way++) {
208 nr = ppc6xx_tlb_getnum(env, eaddr, way, access_type == MMU_INST_FETCH);
209 tlb = &env->tlb.tlb6[nr];
210 /* This test "emulates" the PTE index match for hardware TLBs */
211 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
212 qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx
213 " " TARGET_FMT_lx "] <> " TARGET_FMT_lx "\n",
214 nr, env->nb_tlb,
215 pte_is_valid(tlb->pte0) ? "valid" : "inval",
216 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
217 continue;
219 qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s " TARGET_FMT_lx " <> "
220 TARGET_FMT_lx " " TARGET_FMT_lx " %c %c\n",
221 nr, env->nb_tlb,
222 pte_is_valid(tlb->pte0) ? "valid" : "inval",
223 tlb->EPN, eaddr, tlb->pte1,
224 access_type == MMU_DATA_STORE ? 'S' : 'L',
225 access_type == MMU_INST_FETCH ? 'I' : 'D');
226 switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1,
227 0, access_type)) {
228 case -3:
229 /* TLB inconsistency */
230 return -1;
231 case -2:
232 /* Access violation */
233 ret = -2;
234 best = nr;
235 break;
236 case -1:
237 default:
238 /* No match */
239 break;
240 case 0:
241 /* access granted */
243 * XXX: we should go on looping to check all TLBs
244 * consistency but we can speed-up the whole thing as
245 * the result would be undefined if TLBs are not
246 * consistent.
248 ret = 0;
249 best = nr;
250 goto done;
253 if (best != -1) {
254 done:
255 qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx
256 " prot=%01x ret=%d\n",
257 ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
258 /* Update page flags */
259 pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, access_type);
262 return ret;
265 /* Perform BAT hit & translation */
266 static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
267 int *validp, int *protp, target_ulong *BATu,
268 target_ulong *BATl)
270 target_ulong bl;
271 int pp, valid, prot;
273 bl = (*BATu & 0x00001FFC) << 15;
274 valid = 0;
275 prot = 0;
276 if ((!FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000002)) ||
277 (FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000001))) {
278 valid = 1;
279 pp = *BATl & 0x00000003;
280 if (pp != 0) {
281 prot = PAGE_READ | PAGE_EXEC;
282 if (pp == 0x2) {
283 prot |= PAGE_WRITE;
287 *blp = bl;
288 *validp = valid;
289 *protp = prot;
292 static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
293 target_ulong virtual, MMUAccessType access_type)
295 target_ulong *BATlt, *BATut, *BATu, *BATl;
296 target_ulong BEPIl, BEPIu, bl;
297 int i, valid, prot;
298 int ret = -1;
299 bool ifetch = access_type == MMU_INST_FETCH;
301 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
302 ifetch ? 'I' : 'D', virtual);
303 if (ifetch) {
304 BATlt = env->IBAT[1];
305 BATut = env->IBAT[0];
306 } else {
307 BATlt = env->DBAT[1];
308 BATut = env->DBAT[0];
310 for (i = 0; i < env->nb_BATs; i++) {
311 BATu = &BATut[i];
312 BATl = &BATlt[i];
313 BEPIu = *BATu & 0xF0000000;
314 BEPIl = *BATu & 0x0FFE0000;
315 bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
316 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
317 TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
318 ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
319 if ((virtual & 0xF0000000) == BEPIu &&
320 ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
321 /* BAT matches */
322 if (valid != 0) {
323 /* Get physical address */
324 ctx->raddr = (*BATl & 0xF0000000) |
325 ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
326 (virtual & 0x0001F000);
327 /* Compute access rights */
328 ctx->prot = prot;
329 ret = check_prot(ctx->prot, access_type);
330 if (ret == 0) {
331 qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " HWADDR_FMT_plx
332 " prot=%c%c\n", i, ctx->raddr,
333 ctx->prot & PAGE_READ ? 'R' : '-',
334 ctx->prot & PAGE_WRITE ? 'W' : '-');
336 break;
340 if (ret < 0) {
341 if (qemu_log_enabled()) {
342 qemu_log_mask(CPU_LOG_MMU, "no BAT match for "
343 TARGET_FMT_lx ":\n", virtual);
344 for (i = 0; i < 4; i++) {
345 BATu = &BATut[i];
346 BATl = &BATlt[i];
347 BEPIu = *BATu & 0xF0000000;
348 BEPIl = *BATu & 0x0FFE0000;
349 bl = (*BATu & 0x00001FFC) << 15;
350 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v "
351 TARGET_FMT_lx " BATu " TARGET_FMT_lx
352 " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
353 TARGET_FMT_lx " " TARGET_FMT_lx "\n",
354 __func__, ifetch ? 'I' : 'D', i, virtual,
355 *BATu, *BATl, BEPIu, BEPIl, bl);
359 /* No hit */
360 return ret;
363 /* Perform segment based translation */
364 static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
365 target_ulong eaddr, MMUAccessType access_type,
366 int type)
368 PowerPCCPU *cpu = env_archcpu(env);
369 hwaddr hash;
370 target_ulong vsid;
371 int ds, target_page_bits;
372 bool pr;
373 int ret;
374 target_ulong sr, pgidx;
376 pr = FIELD_EX64(env->msr, MSR, PR);
377 ctx->eaddr = eaddr;
379 sr = env->sr[eaddr >> 28];
380 ctx->key = (((sr & 0x20000000) && pr) ||
381 ((sr & 0x40000000) && !pr)) ? 1 : 0;
382 ds = sr & 0x80000000 ? 1 : 0;
383 ctx->nx = sr & 0x10000000 ? 1 : 0;
384 vsid = sr & 0x00FFFFFF;
385 target_page_bits = TARGET_PAGE_BITS;
386 qemu_log_mask(CPU_LOG_MMU,
387 "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
388 " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
389 " ir=%d dr=%d pr=%d %d t=%d\n",
390 eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr,
391 (int)FIELD_EX64(env->msr, MSR, IR),
392 (int)FIELD_EX64(env->msr, MSR, DR), pr ? 1 : 0,
393 access_type == MMU_DATA_STORE, type);
394 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
395 hash = vsid ^ pgidx;
396 ctx->ptem = (vsid << 7) | (pgidx >> 10);
398 qemu_log_mask(CPU_LOG_MMU,
399 "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
400 ctx->key, ds, ctx->nx, vsid);
401 ret = -1;
402 if (!ds) {
403 /* Check if instruction fetch is allowed, if needed */
404 if (type != ACCESS_CODE || ctx->nx == 0) {
405 /* Page address translation */
406 qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx
407 " htab_mask " HWADDR_FMT_plx
408 " hash " HWADDR_FMT_plx "\n",
409 ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
410 ctx->hash[0] = hash;
411 ctx->hash[1] = ~hash;
413 /* Initialize real address with an invalid value */
414 ctx->raddr = (hwaddr)-1ULL;
415 /* Software TLB search */
416 ret = ppc6xx_tlb_check(env, ctx, eaddr, access_type);
417 #if defined(DUMP_PAGE_TABLES)
418 if (qemu_loglevel_mask(CPU_LOG_MMU)) {
419 CPUState *cs = env_cpu(env);
420 hwaddr curaddr;
421 uint32_t a0, a1, a2, a3;
423 qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx
424 "\n", ppc_hash32_hpt_base(cpu),
425 ppc_hash32_hpt_mask(cpu) + 0x80);
426 for (curaddr = ppc_hash32_hpt_base(cpu);
427 curaddr < (ppc_hash32_hpt_base(cpu)
428 + ppc_hash32_hpt_mask(cpu) + 0x80);
429 curaddr += 16) {
430 a0 = ldl_phys(cs->as, curaddr);
431 a1 = ldl_phys(cs->as, curaddr + 4);
432 a2 = ldl_phys(cs->as, curaddr + 8);
433 a3 = ldl_phys(cs->as, curaddr + 12);
434 if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
435 qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
436 curaddr, a0, a1, a2, a3);
440 #endif
441 } else {
442 qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
443 ret = -3;
445 } else {
446 qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
447 /* Direct-store segment : absolutely *BUGGY* for now */
449 switch (type) {
450 case ACCESS_INT:
451 /* Integer load/store : only access allowed */
452 break;
453 case ACCESS_CODE:
454 /* No code fetch is allowed in direct-store areas */
455 return -4;
456 case ACCESS_FLOAT:
457 /* Floating point load/store */
458 return -4;
459 case ACCESS_RES:
460 /* lwarx, ldarx or srwcx. */
461 return -4;
462 case ACCESS_CACHE:
464 * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
466 * Should make the instruction do no-op. As it already do
467 * no-op, it's quite easy :-)
469 ctx->raddr = eaddr;
470 return 0;
471 case ACCESS_EXT:
472 /* eciwx or ecowx */
473 return -4;
474 default:
475 qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need "
476 "address translation\n");
477 return -4;
479 if ((access_type == MMU_DATA_STORE || ctx->key != 1) &&
480 (access_type == MMU_DATA_LOAD || ctx->key != 0)) {
481 ctx->raddr = eaddr;
482 ret = 2;
483 } else {
484 ret = -2;
488 return ret;
491 /* Generic TLB check function for embedded PowerPC implementations */
492 static bool ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
493 hwaddr *raddrp,
494 target_ulong address, uint32_t pid, int i)
496 target_ulong mask;
498 /* Check valid flag */
499 if (!(tlb->prot & PAGE_VALID)) {
500 return false;
502 mask = ~(tlb->size - 1);
503 qemu_log_mask(CPU_LOG_MMU, "%s: TLB %d address " TARGET_FMT_lx
504 " PID %u <=> " TARGET_FMT_lx " " TARGET_FMT_lx " %u %x\n",
505 __func__, i, address, pid, tlb->EPN,
506 mask, (uint32_t)tlb->PID, tlb->prot);
507 /* Check PID */
508 if (tlb->PID != 0 && tlb->PID != pid) {
509 return false;
511 /* Check effective address */
512 if ((address & mask) != tlb->EPN) {
513 return false;
515 *raddrp = (tlb->RPN & mask) | (address & ~mask);
516 return true;
519 /* Generic TLB search function for PowerPC embedded implementations */
520 int ppcemb_tlb_search(CPUPPCState *env, target_ulong address, uint32_t pid)
522 ppcemb_tlb_t *tlb;
523 hwaddr raddr;
524 int i;
526 for (i = 0; i < env->nb_tlb; i++) {
527 tlb = &env->tlb.tlbe[i];
528 if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, i)) {
529 return i;
532 return -1;
535 static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
536 target_ulong address,
537 MMUAccessType access_type)
539 ppcemb_tlb_t *tlb;
540 hwaddr raddr;
541 int i, ret, zsel, zpr, pr;
543 ret = -1;
544 raddr = (hwaddr)-1ULL;
545 pr = FIELD_EX64(env->msr, MSR, PR);
546 for (i = 0; i < env->nb_tlb; i++) {
547 tlb = &env->tlb.tlbe[i];
548 if (!ppcemb_tlb_check(env, tlb, &raddr, address,
549 env->spr[SPR_40x_PID], i)) {
550 continue;
552 zsel = (tlb->attr >> 4) & 0xF;
553 zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
554 qemu_log_mask(CPU_LOG_MMU,
555 "%s: TLB %d zsel %d zpr %d ty %d attr %08x\n",
556 __func__, i, zsel, zpr, access_type, tlb->attr);
557 /* Check execute enable bit */
558 switch (zpr) {
559 case 0x2:
560 if (pr != 0) {
561 goto check_perms;
563 /* fall through */
564 case 0x3:
565 /* All accesses granted */
566 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
567 ret = 0;
568 break;
569 case 0x0:
570 if (pr != 0) {
571 /* Raise Zone protection fault. */
572 env->spr[SPR_40x_ESR] = 1 << 22;
573 ctx->prot = 0;
574 ret = -2;
575 break;
577 /* fall through */
578 case 0x1:
579 check_perms:
580 /* Check from TLB entry */
581 ctx->prot = tlb->prot;
582 ret = check_prot(ctx->prot, access_type);
583 if (ret == -2) {
584 env->spr[SPR_40x_ESR] = 0;
586 break;
588 if (ret >= 0) {
589 ctx->raddr = raddr;
590 qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx
591 " => " HWADDR_FMT_plx
592 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
593 ret);
594 return 0;
597 qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
598 " => " HWADDR_FMT_plx
599 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
601 return ret;
604 static int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb,
605 hwaddr *raddr, int *prot, target_ulong address,
606 MMUAccessType access_type, int i)
608 int prot2;
610 if (ppcemb_tlb_check(env, tlb, raddr, address,
611 env->spr[SPR_BOOKE_PID], i)) {
612 if (!env->nb_pids) {
613 /* Extend the physical address to 36 bits */
614 *raddr |= (uint64_t)(tlb->RPN & 0xF) << 32;
616 goto found_tlb;
619 if (env->spr[SPR_BOOKE_PID1] &&
620 ppcemb_tlb_check(env, tlb, raddr, address,
621 env->spr[SPR_BOOKE_PID1], i)) {
622 goto found_tlb;
625 if (env->spr[SPR_BOOKE_PID2] &&
626 ppcemb_tlb_check(env, tlb, raddr, address,
627 env->spr[SPR_BOOKE_PID2], i)) {
628 goto found_tlb;
631 qemu_log_mask(CPU_LOG_MMU, "%s: TLB entry not found\n", __func__);
632 return -1;
634 found_tlb:
636 if (FIELD_EX64(env->msr, MSR, PR)) {
637 prot2 = tlb->prot & 0xF;
638 } else {
639 prot2 = (tlb->prot >> 4) & 0xF;
642 /* Check the address space */
643 if ((access_type == MMU_INST_FETCH ?
644 FIELD_EX64(env->msr, MSR, IR) :
645 FIELD_EX64(env->msr, MSR, DR)) != (tlb->attr & 1)) {
646 qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__);
647 return -1;
650 *prot = prot2;
651 if (prot2 & prot_for_access_type(access_type)) {
652 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
653 return 0;
656 qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, prot2);
657 return access_type == MMU_INST_FETCH ? -3 : -2;
660 static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
661 target_ulong address,
662 MMUAccessType access_type)
664 ppcemb_tlb_t *tlb;
665 hwaddr raddr;
666 int i, ret;
668 ret = -1;
669 raddr = (hwaddr)-1ULL;
670 for (i = 0; i < env->nb_tlb; i++) {
671 tlb = &env->tlb.tlbe[i];
672 ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address,
673 access_type, i);
674 if (ret != -1) {
675 break;
679 if (ret >= 0) {
680 ctx->raddr = raddr;
681 qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx
682 " => " HWADDR_FMT_plx " %d %d\n", __func__,
683 address, ctx->raddr, ctx->prot, ret);
684 } else {
685 qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
686 " => " HWADDR_FMT_plx " %d %d\n", __func__,
687 address, raddr, ctx->prot, ret);
690 return ret;
693 hwaddr booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb)
695 int tlbm_size;
697 tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
699 return 1024ULL << tlbm_size;
702 /* TLB check function for MAS based SoftTLBs */
703 int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, hwaddr *raddrp,
704 target_ulong address, uint32_t pid)
706 hwaddr mask;
707 uint32_t tlb_pid;
709 if (!FIELD_EX64(env->msr, MSR, CM)) {
710 /* In 32bit mode we can only address 32bit EAs */
711 address = (uint32_t)address;
714 /* Check valid flag */
715 if (!(tlb->mas1 & MAS1_VALID)) {
716 return -1;
719 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
720 qemu_log_mask(CPU_LOG_MMU, "%s: TLB ADDR=0x" TARGET_FMT_lx
721 " PID=0x%x MAS1=0x%x MAS2=0x%" PRIx64 " mask=0x%"
722 HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" PRIx32 "\n",
723 __func__, address, pid, tlb->mas1, tlb->mas2, mask,
724 tlb->mas7_3, tlb->mas8);
726 /* Check PID */
727 tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
728 if (tlb_pid != 0 && tlb_pid != pid) {
729 return -1;
732 /* Check effective address */
733 if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
734 return -1;
737 if (raddrp) {
738 *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
741 return 0;
744 static bool is_epid_mmu(int mmu_idx)
746 return mmu_idx == PPC_TLB_EPID_STORE || mmu_idx == PPC_TLB_EPID_LOAD;
749 static uint32_t mmubooke206_esr(int mmu_idx, MMUAccessType access_type)
751 uint32_t esr = 0;
752 if (access_type == MMU_DATA_STORE) {
753 esr |= ESR_ST;
755 if (is_epid_mmu(mmu_idx)) {
756 esr |= ESR_EPID;
758 return esr;
762 * Get EPID register given the mmu_idx. If this is regular load,
763 * construct the EPID access bits from current processor state
765 * Get the effective AS and PR bits and the PID. The PID is returned
766 * only if EPID load is requested, otherwise the caller must detect
767 * the correct EPID. Return true if valid EPID is returned.
769 static bool mmubooke206_get_as(CPUPPCState *env,
770 int mmu_idx, uint32_t *epid_out,
771 bool *as_out, bool *pr_out)
773 if (is_epid_mmu(mmu_idx)) {
774 uint32_t epidr;
775 if (mmu_idx == PPC_TLB_EPID_STORE) {
776 epidr = env->spr[SPR_BOOKE_EPSC];
777 } else {
778 epidr = env->spr[SPR_BOOKE_EPLC];
780 *epid_out = (epidr & EPID_EPID) >> EPID_EPID_SHIFT;
781 *as_out = !!(epidr & EPID_EAS);
782 *pr_out = !!(epidr & EPID_EPR);
783 return true;
784 } else {
785 *as_out = FIELD_EX64(env->msr, MSR, DS);
786 *pr_out = FIELD_EX64(env->msr, MSR, PR);
787 return false;
791 /* Check if the tlb found by hashing really matches */
792 static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
793 hwaddr *raddr, int *prot,
794 target_ulong address,
795 MMUAccessType access_type, int mmu_idx)
797 int prot2 = 0;
798 uint32_t epid;
799 bool as, pr;
800 bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
802 if (!use_epid) {
803 if (ppcmas_tlb_check(env, tlb, raddr, address,
804 env->spr[SPR_BOOKE_PID]) >= 0) {
805 goto found_tlb;
808 if (env->spr[SPR_BOOKE_PID1] &&
809 ppcmas_tlb_check(env, tlb, raddr, address,
810 env->spr[SPR_BOOKE_PID1]) >= 0) {
811 goto found_tlb;
814 if (env->spr[SPR_BOOKE_PID2] &&
815 ppcmas_tlb_check(env, tlb, raddr, address,
816 env->spr[SPR_BOOKE_PID2]) >= 0) {
817 goto found_tlb;
819 } else {
820 if (ppcmas_tlb_check(env, tlb, raddr, address, epid) >= 0) {
821 goto found_tlb;
825 qemu_log_mask(CPU_LOG_MMU, "%s: No TLB entry found for effective address "
826 "0x" TARGET_FMT_lx "\n", __func__, address);
827 return -1;
829 found_tlb:
831 if (pr) {
832 if (tlb->mas7_3 & MAS3_UR) {
833 prot2 |= PAGE_READ;
835 if (tlb->mas7_3 & MAS3_UW) {
836 prot2 |= PAGE_WRITE;
838 if (tlb->mas7_3 & MAS3_UX) {
839 prot2 |= PAGE_EXEC;
841 } else {
842 if (tlb->mas7_3 & MAS3_SR) {
843 prot2 |= PAGE_READ;
845 if (tlb->mas7_3 & MAS3_SW) {
846 prot2 |= PAGE_WRITE;
848 if (tlb->mas7_3 & MAS3_SX) {
849 prot2 |= PAGE_EXEC;
853 /* Check the address space and permissions */
854 if (access_type == MMU_INST_FETCH) {
855 /* There is no way to fetch code using epid load */
856 assert(!use_epid);
857 as = FIELD_EX64(env->msr, MSR, IR);
860 if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
861 qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__);
862 return -1;
865 *prot = prot2;
866 if (prot2 & prot_for_access_type(access_type)) {
867 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
868 return 0;
871 qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, prot2);
872 return access_type == MMU_INST_FETCH ? -3 : -2;
875 static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
876 target_ulong address,
877 MMUAccessType access_type,
878 int mmu_idx)
880 ppcmas_tlb_t *tlb;
881 hwaddr raddr;
882 int i, j, ret;
884 ret = -1;
885 raddr = (hwaddr)-1ULL;
887 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
888 int ways = booke206_tlb_ways(env, i);
890 for (j = 0; j < ways; j++) {
891 tlb = booke206_get_tlbm(env, i, address, j);
892 if (!tlb) {
893 continue;
895 ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
896 access_type, mmu_idx);
897 if (ret != -1) {
898 goto found_tlb;
903 found_tlb:
905 if (ret >= 0) {
906 ctx->raddr = raddr;
907 qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx
908 " => " HWADDR_FMT_plx " %d %d\n", __func__, address,
909 ctx->raddr, ctx->prot, ret);
910 } else {
911 qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
912 " => " HWADDR_FMT_plx " %d %d\n", __func__, address,
913 raddr, ctx->prot, ret);
916 return ret;
919 static const char *book3e_tsize_to_str[32] = {
920 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
921 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
922 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
923 "1T", "2T"
926 static void mmubooke_dump_mmu(CPUPPCState *env)
928 ppcemb_tlb_t *entry;
929 int i;
931 if (kvm_enabled() && !env->kvm_sw_tlb) {
932 qemu_printf("Cannot access KVM TLB\n");
933 return;
936 qemu_printf("\nTLB:\n");
937 qemu_printf("Effective Physical Size PID Prot "
938 "Attr\n");
940 entry = &env->tlb.tlbe[0];
941 for (i = 0; i < env->nb_tlb; i++, entry++) {
942 hwaddr ea, pa;
943 target_ulong mask;
944 uint64_t size = (uint64_t)entry->size;
945 char size_buf[20];
947 /* Check valid flag */
948 if (!(entry->prot & PAGE_VALID)) {
949 continue;
952 mask = ~(entry->size - 1);
953 ea = entry->EPN & mask;
954 pa = entry->RPN & mask;
955 /* Extend the physical address to 36 bits */
956 pa |= (hwaddr)(entry->RPN & 0xF) << 32;
957 if (size >= 1 * MiB) {
958 snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB);
959 } else {
960 snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB);
962 qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
963 (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
964 entry->prot, entry->attr);
969 static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset,
970 int tlbsize)
972 ppcmas_tlb_t *entry;
973 int i;
975 qemu_printf("\nTLB%d:\n", tlbn);
976 qemu_printf("Effective Physical Size TID TS SRWX"
977 " URWX WIMGE U0123\n");
979 entry = &env->tlb.tlbm[offset];
980 for (i = 0; i < tlbsize; i++, entry++) {
981 hwaddr ea, pa, size;
982 int tsize;
984 if (!(entry->mas1 & MAS1_VALID)) {
985 continue;
988 tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
989 size = 1024ULL << tsize;
990 ea = entry->mas2 & ~(size - 1);
991 pa = entry->mas7_3 & ~(size - 1);
993 qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u S%c%c%c"
994 " U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
995 (uint64_t)ea, (uint64_t)pa,
996 book3e_tsize_to_str[tsize],
997 (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
998 (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
999 entry->mas7_3 & MAS3_SR ? 'R' : '-',
1000 entry->mas7_3 & MAS3_SW ? 'W' : '-',
1001 entry->mas7_3 & MAS3_SX ? 'X' : '-',
1002 entry->mas7_3 & MAS3_UR ? 'R' : '-',
1003 entry->mas7_3 & MAS3_UW ? 'W' : '-',
1004 entry->mas7_3 & MAS3_UX ? 'X' : '-',
1005 entry->mas2 & MAS2_W ? 'W' : '-',
1006 entry->mas2 & MAS2_I ? 'I' : '-',
1007 entry->mas2 & MAS2_M ? 'M' : '-',
1008 entry->mas2 & MAS2_G ? 'G' : '-',
1009 entry->mas2 & MAS2_E ? 'E' : '-',
1010 entry->mas7_3 & MAS3_U0 ? '0' : '-',
1011 entry->mas7_3 & MAS3_U1 ? '1' : '-',
1012 entry->mas7_3 & MAS3_U2 ? '2' : '-',
1013 entry->mas7_3 & MAS3_U3 ? '3' : '-');
1017 static void mmubooke206_dump_mmu(CPUPPCState *env)
1019 int offset = 0;
1020 int i;
1022 if (kvm_enabled() && !env->kvm_sw_tlb) {
1023 qemu_printf("Cannot access KVM TLB\n");
1024 return;
1027 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1028 int size = booke206_tlb_size(env, i);
1030 if (size == 0) {
1031 continue;
1034 mmubooke206_dump_one_tlb(env, i, offset, size);
1035 offset += size;
1039 static void mmu6xx_dump_BATs(CPUPPCState *env, int type)
1041 target_ulong *BATlt, *BATut, *BATu, *BATl;
1042 target_ulong BEPIl, BEPIu, bl;
1043 int i;
1045 switch (type) {
1046 case ACCESS_CODE:
1047 BATlt = env->IBAT[1];
1048 BATut = env->IBAT[0];
1049 break;
1050 default:
1051 BATlt = env->DBAT[1];
1052 BATut = env->DBAT[0];
1053 break;
1056 for (i = 0; i < env->nb_BATs; i++) {
1057 BATu = &BATut[i];
1058 BATl = &BATlt[i];
1059 BEPIu = *BATu & 0xF0000000;
1060 BEPIl = *BATu & 0x0FFE0000;
1061 bl = (*BATu & 0x00001FFC) << 15;
1062 qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
1063 " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
1064 TARGET_FMT_lx " " TARGET_FMT_lx "\n",
1065 type == ACCESS_CODE ? "code" : "data", i,
1066 *BATu, *BATl, BEPIu, BEPIl, bl);
1070 static void mmu6xx_dump_mmu(CPUPPCState *env)
1072 PowerPCCPU *cpu = env_archcpu(env);
1073 ppc6xx_tlb_t *tlb;
1074 target_ulong sr;
1075 int type, way, entry, i;
1077 qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu));
1078 qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu));
1080 qemu_printf("\nSegment registers:\n");
1081 for (i = 0; i < 32; i++) {
1082 sr = env->sr[i];
1083 if (sr & 0x80000000) {
1084 qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1085 "CNTLR_SPEC=0x%05x\n", i,
1086 sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
1087 sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF),
1088 (uint32_t)(sr & 0xFFFFF));
1089 } else {
1090 qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i,
1091 sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
1092 sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0,
1093 (uint32_t)(sr & 0x00FFFFFF));
1097 qemu_printf("\nBATs:\n");
1098 mmu6xx_dump_BATs(env, ACCESS_INT);
1099 mmu6xx_dump_BATs(env, ACCESS_CODE);
1101 if (env->id_tlbs != 1) {
1102 qemu_printf("ERROR: 6xx MMU should have separated TLB"
1103 " for code and data\n");
1106 qemu_printf("\nTLBs [EPN EPN + SIZE]\n");
1108 for (type = 0; type < 2; type++) {
1109 for (way = 0; way < env->nb_ways; way++) {
1110 for (entry = env->nb_tlb * type + env->tlb_per_way * way;
1111 entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1));
1112 entry++) {
1114 tlb = &env->tlb.tlb6[entry];
1115 qemu_printf("%s TLB %02d/%02d way:%d %s ["
1116 TARGET_FMT_lx " " TARGET_FMT_lx "]\n",
1117 type ? "code" : "data", entry % env->nb_tlb,
1118 env->nb_tlb, way,
1119 pte_is_valid(tlb->pte0) ? "valid" : "inval",
1120 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE);
1126 void dump_mmu(CPUPPCState *env)
1128 switch (env->mmu_model) {
1129 case POWERPC_MMU_BOOKE:
1130 mmubooke_dump_mmu(env);
1131 break;
1132 case POWERPC_MMU_BOOKE206:
1133 mmubooke206_dump_mmu(env);
1134 break;
1135 case POWERPC_MMU_SOFT_6xx:
1136 mmu6xx_dump_mmu(env);
1137 break;
1138 #if defined(TARGET_PPC64)
1139 case POWERPC_MMU_64B:
1140 case POWERPC_MMU_2_03:
1141 case POWERPC_MMU_2_06:
1142 case POWERPC_MMU_2_07:
1143 dump_slb(env_archcpu(env));
1144 break;
1145 case POWERPC_MMU_3_00:
1146 if (ppc64_v3_radix(env_archcpu(env))) {
1147 qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n",
1148 __func__);
1149 } else {
1150 dump_slb(env_archcpu(env));
1152 break;
1153 #endif
1154 default:
1155 qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
1159 static int check_physical(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1160 MMUAccessType access_type)
1162 ctx->raddr = eaddr;
1163 ctx->prot = PAGE_READ | PAGE_EXEC;
1165 switch (env->mmu_model) {
1166 case POWERPC_MMU_SOFT_6xx:
1167 case POWERPC_MMU_SOFT_4xx:
1168 case POWERPC_MMU_REAL:
1169 case POWERPC_MMU_BOOKE:
1170 ctx->prot |= PAGE_WRITE;
1171 break;
1173 default:
1174 /* Caller's checks mean we should never get here for other models */
1175 g_assert_not_reached();
1178 return 0;
1181 int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
1182 target_ulong eaddr,
1183 MMUAccessType access_type, int type,
1184 int mmu_idx)
1186 int ret = -1;
1187 bool real_mode = (type == ACCESS_CODE && !FIELD_EX64(env->msr, MSR, IR)) ||
1188 (type != ACCESS_CODE && !FIELD_EX64(env->msr, MSR, DR));
1190 switch (env->mmu_model) {
1191 case POWERPC_MMU_SOFT_6xx:
1192 if (real_mode) {
1193 ret = check_physical(env, ctx, eaddr, access_type);
1194 } else {
1195 /* Try to find a BAT */
1196 if (env->nb_BATs != 0) {
1197 ret = get_bat_6xx_tlb(env, ctx, eaddr, access_type);
1199 if (ret < 0) {
1200 /* We didn't match any BAT entry or don't have BATs */
1201 ret = get_segment_6xx_tlb(env, ctx, eaddr, access_type, type);
1204 break;
1206 case POWERPC_MMU_SOFT_4xx:
1207 if (real_mode) {
1208 ret = check_physical(env, ctx, eaddr, access_type);
1209 } else {
1210 ret = mmu40x_get_physical_address(env, ctx, eaddr, access_type);
1212 break;
1213 case POWERPC_MMU_BOOKE:
1214 ret = mmubooke_get_physical_address(env, ctx, eaddr, access_type);
1215 break;
1216 case POWERPC_MMU_BOOKE206:
1217 ret = mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
1218 mmu_idx);
1219 break;
1220 case POWERPC_MMU_MPC8xx:
1221 /* XXX: TODO */
1222 cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
1223 break;
1224 case POWERPC_MMU_REAL:
1225 if (real_mode) {
1226 ret = check_physical(env, ctx, eaddr, access_type);
1227 } else {
1228 cpu_abort(env_cpu(env),
1229 "PowerPC in real mode do not do any translation\n");
1231 return -1;
1232 default:
1233 cpu_abort(env_cpu(env), "Unknown or invalid MMU model\n");
1234 return -1;
1237 return ret;
1240 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
1241 MMUAccessType access_type, int mmu_idx)
1243 uint32_t epid;
1244 bool as, pr;
1245 uint32_t missed_tid = 0;
1246 bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
1248 if (access_type == MMU_INST_FETCH) {
1249 as = FIELD_EX64(env->msr, MSR, IR);
1251 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1252 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1253 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1254 env->spr[SPR_BOOKE_MAS3] = 0;
1255 env->spr[SPR_BOOKE_MAS6] = 0;
1256 env->spr[SPR_BOOKE_MAS7] = 0;
1258 /* AS */
1259 if (as) {
1260 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1261 env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1264 env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1265 env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1267 if (!use_epid) {
1268 switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1269 case MAS4_TIDSELD_PID0:
1270 missed_tid = env->spr[SPR_BOOKE_PID];
1271 break;
1272 case MAS4_TIDSELD_PID1:
1273 missed_tid = env->spr[SPR_BOOKE_PID1];
1274 break;
1275 case MAS4_TIDSELD_PID2:
1276 missed_tid = env->spr[SPR_BOOKE_PID2];
1277 break;
1279 env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1280 } else {
1281 missed_tid = epid;
1282 env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
1284 env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
1287 /* next victim logic */
1288 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1289 env->last_way++;
1290 env->last_way &= booke206_tlb_ways(env, 0) - 1;
1291 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1294 /* Perform address translation */
1295 /* TODO: Split this by mmu_model. */
1296 static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
1297 MMUAccessType access_type,
1298 hwaddr *raddrp, int *psizep, int *protp,
1299 int mmu_idx, bool guest_visible)
1301 CPUState *cs = CPU(cpu);
1302 CPUPPCState *env = &cpu->env;
1303 mmu_ctx_t ctx;
1304 int type;
1305 int ret;
1307 if (access_type == MMU_INST_FETCH) {
1308 /* code access */
1309 type = ACCESS_CODE;
1310 } else if (guest_visible) {
1311 /* data access */
1312 type = env->access_type;
1313 } else {
1314 type = ACCESS_INT;
1317 ret = get_physical_address_wtlb(env, &ctx, eaddr, access_type,
1318 type, mmu_idx);
1319 if (ret == 0) {
1320 *raddrp = ctx.raddr;
1321 *protp = ctx.prot;
1322 *psizep = TARGET_PAGE_BITS;
1323 return true;
1326 if (guest_visible) {
1327 log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
1328 if (type == ACCESS_CODE) {
1329 switch (ret) {
1330 case -1:
1331 /* No matches in page tables or TLB */
1332 switch (env->mmu_model) {
1333 case POWERPC_MMU_SOFT_6xx:
1334 cs->exception_index = POWERPC_EXCP_IFTLB;
1335 env->error_code = 1 << 18;
1336 env->spr[SPR_IMISS] = eaddr;
1337 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1338 goto tlb_miss;
1339 case POWERPC_MMU_SOFT_4xx:
1340 cs->exception_index = POWERPC_EXCP_ITLB;
1341 env->error_code = 0;
1342 env->spr[SPR_40x_DEAR] = eaddr;
1343 env->spr[SPR_40x_ESR] = 0x00000000;
1344 break;
1345 case POWERPC_MMU_BOOKE206:
1346 booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
1347 /* fall through */
1348 case POWERPC_MMU_BOOKE:
1349 cs->exception_index = POWERPC_EXCP_ITLB;
1350 env->error_code = 0;
1351 env->spr[SPR_BOOKE_DEAR] = eaddr;
1352 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, MMU_DATA_LOAD);
1353 break;
1354 case POWERPC_MMU_MPC8xx:
1355 cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
1356 case POWERPC_MMU_REAL:
1357 cpu_abort(cs, "PowerPC in real mode should never raise "
1358 "any MMU exceptions\n");
1359 default:
1360 cpu_abort(cs, "Unknown or invalid MMU model\n");
1362 break;
1363 case -2:
1364 /* Access rights violation */
1365 cs->exception_index = POWERPC_EXCP_ISI;
1366 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1367 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1368 env->error_code = 0;
1369 } else {
1370 env->error_code = 0x08000000;
1372 break;
1373 case -3:
1374 /* No execute protection violation */
1375 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1376 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1377 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1378 env->error_code = 0;
1379 } else {
1380 env->error_code = 0x10000000;
1382 cs->exception_index = POWERPC_EXCP_ISI;
1383 break;
1384 case -4:
1385 /* Direct store exception */
1386 /* No code fetch is allowed in direct-store areas */
1387 cs->exception_index = POWERPC_EXCP_ISI;
1388 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1389 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1390 env->error_code = 0;
1391 } else {
1392 env->error_code = 0x10000000;
1394 break;
1396 } else {
1397 switch (ret) {
1398 case -1:
1399 /* No matches in page tables or TLB */
1400 switch (env->mmu_model) {
1401 case POWERPC_MMU_SOFT_6xx:
1402 if (access_type == MMU_DATA_STORE) {
1403 cs->exception_index = POWERPC_EXCP_DSTLB;
1404 env->error_code = 1 << 16;
1405 } else {
1406 cs->exception_index = POWERPC_EXCP_DLTLB;
1407 env->error_code = 0;
1409 env->spr[SPR_DMISS] = eaddr;
1410 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1411 tlb_miss:
1412 env->error_code |= ctx.key << 19;
1413 env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
1414 get_pteg_offset32(cpu, ctx.hash[0]);
1415 env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
1416 get_pteg_offset32(cpu, ctx.hash[1]);
1417 break;
1418 case POWERPC_MMU_SOFT_4xx:
1419 cs->exception_index = POWERPC_EXCP_DTLB;
1420 env->error_code = 0;
1421 env->spr[SPR_40x_DEAR] = eaddr;
1422 if (access_type == MMU_DATA_STORE) {
1423 env->spr[SPR_40x_ESR] = 0x00800000;
1424 } else {
1425 env->spr[SPR_40x_ESR] = 0x00000000;
1427 break;
1428 case POWERPC_MMU_MPC8xx:
1429 /* XXX: TODO */
1430 cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
1431 case POWERPC_MMU_BOOKE206:
1432 booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
1433 /* fall through */
1434 case POWERPC_MMU_BOOKE:
1435 cs->exception_index = POWERPC_EXCP_DTLB;
1436 env->error_code = 0;
1437 env->spr[SPR_BOOKE_DEAR] = eaddr;
1438 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
1439 break;
1440 case POWERPC_MMU_REAL:
1441 cpu_abort(cs, "PowerPC in real mode should never raise "
1442 "any MMU exceptions\n");
1443 default:
1444 cpu_abort(cs, "Unknown or invalid MMU model\n");
1446 break;
1447 case -2:
1448 /* Access rights violation */
1449 cs->exception_index = POWERPC_EXCP_DSI;
1450 env->error_code = 0;
1451 if (env->mmu_model == POWERPC_MMU_SOFT_4xx) {
1452 env->spr[SPR_40x_DEAR] = eaddr;
1453 if (access_type == MMU_DATA_STORE) {
1454 env->spr[SPR_40x_ESR] |= 0x00800000;
1456 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1457 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1458 env->spr[SPR_BOOKE_DEAR] = eaddr;
1459 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
1460 } else {
1461 env->spr[SPR_DAR] = eaddr;
1462 if (access_type == MMU_DATA_STORE) {
1463 env->spr[SPR_DSISR] = 0x0A000000;
1464 } else {
1465 env->spr[SPR_DSISR] = 0x08000000;
1468 break;
1469 case -4:
1470 /* Direct store exception */
1471 switch (type) {
1472 case ACCESS_FLOAT:
1473 /* Floating point load/store */
1474 cs->exception_index = POWERPC_EXCP_ALIGN;
1475 env->error_code = POWERPC_EXCP_ALIGN_FP;
1476 env->spr[SPR_DAR] = eaddr;
1477 break;
1478 case ACCESS_RES:
1479 /* lwarx, ldarx or stwcx. */
1480 cs->exception_index = POWERPC_EXCP_DSI;
1481 env->error_code = 0;
1482 env->spr[SPR_DAR] = eaddr;
1483 if (access_type == MMU_DATA_STORE) {
1484 env->spr[SPR_DSISR] = 0x06000000;
1485 } else {
1486 env->spr[SPR_DSISR] = 0x04000000;
1488 break;
1489 case ACCESS_EXT:
1490 /* eciwx or ecowx */
1491 cs->exception_index = POWERPC_EXCP_DSI;
1492 env->error_code = 0;
1493 env->spr[SPR_DAR] = eaddr;
1494 if (access_type == MMU_DATA_STORE) {
1495 env->spr[SPR_DSISR] = 0x06100000;
1496 } else {
1497 env->spr[SPR_DSISR] = 0x04100000;
1499 break;
1500 default:
1501 printf("DSI: invalid exception (%d)\n", ret);
1502 cs->exception_index = POWERPC_EXCP_PROGRAM;
1503 env->error_code =
1504 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1505 env->spr[SPR_DAR] = eaddr;
1506 break;
1508 break;
1512 return false;
1515 /*****************************************************************************/
1517 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
1518 hwaddr *raddrp, int *psizep, int *protp,
1519 int mmu_idx, bool guest_visible)
1521 switch (cpu->env.mmu_model) {
1522 #if defined(TARGET_PPC64)
1523 case POWERPC_MMU_3_00:
1524 if (ppc64_v3_radix(cpu)) {
1525 return ppc_radix64_xlate(cpu, eaddr, access_type, raddrp,
1526 psizep, protp, mmu_idx, guest_visible);
1528 /* fall through */
1529 case POWERPC_MMU_64B:
1530 case POWERPC_MMU_2_03:
1531 case POWERPC_MMU_2_06:
1532 case POWERPC_MMU_2_07:
1533 return ppc_hash64_xlate(cpu, eaddr, access_type,
1534 raddrp, psizep, protp, mmu_idx, guest_visible);
1535 #endif
1537 case POWERPC_MMU_32B:
1538 return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp,
1539 psizep, protp, mmu_idx, guest_visible);
1541 default:
1542 return ppc_jumbo_xlate(cpu, eaddr, access_type, raddrp,
1543 psizep, protp, mmu_idx, guest_visible);
1547 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
1549 PowerPCCPU *cpu = POWERPC_CPU(cs);
1550 hwaddr raddr;
1551 int s, p;
1554 * Some MMUs have separate TLBs for code and data. If we only
1555 * try an MMU_DATA_LOAD, we may not be able to read instructions
1556 * mapped by code TLBs, so we also try a MMU_INST_FETCH.
1558 if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p,
1559 cpu_mmu_index(&cpu->env, false), false) ||
1560 ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p,
1561 cpu_mmu_index(&cpu->env, true), false)) {
1562 return raddr & TARGET_PAGE_MASK;
1564 return -1;