target/ppc: Remove type argument from mmubooke_get_physical_address
[qemu/ar7.git] / target / ppc / mmu_helper.c
blob7535a1aa7d88f314b0ae82e23764dc9f9210f585
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 "exec/helper-proto.h"
24 #include "sysemu/kvm.h"
25 #include "kvm_ppc.h"
26 #include "mmu-hash64.h"
27 #include "mmu-hash32.h"
28 #include "exec/exec-all.h"
29 #include "exec/cpu_ldst.h"
30 #include "exec/log.h"
31 #include "helper_regs.h"
32 #include "qemu/error-report.h"
33 #include "qemu/main-loop.h"
34 #include "qemu/qemu-print.h"
35 #include "internal.h"
36 #include "mmu-book3s-v3.h"
37 #include "mmu-radix64.h"
39 /* #define DEBUG_MMU */
40 /* #define DEBUG_BATS */
41 /* #define DEBUG_SOFTWARE_TLB */
42 /* #define DUMP_PAGE_TABLES */
43 /* #define FLUSH_ALL_TLBS */
45 #ifdef DEBUG_MMU
46 # define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0)
47 #else
48 # define LOG_MMU_STATE(cpu) do { } while (0)
49 #endif
51 #ifdef DEBUG_SOFTWARE_TLB
52 # define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
53 #else
54 # define LOG_SWTLB(...) do { } while (0)
55 #endif
57 #ifdef DEBUG_BATS
58 # define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
59 #else
60 # define LOG_BATS(...) do { } while (0)
61 #endif
63 /*****************************************************************************/
64 /* PowerPC MMU emulation */
66 /* Context used internally during MMU translations */
67 typedef struct mmu_ctx_t mmu_ctx_t;
68 struct mmu_ctx_t {
69 hwaddr raddr; /* Real address */
70 hwaddr eaddr; /* Effective address */
71 int prot; /* Protection bits */
72 hwaddr hash[2]; /* Pagetable hash values */
73 target_ulong ptem; /* Virtual segment ID | API */
74 int key; /* Access key */
75 int nx; /* Non-execute area */
78 /* Common routines used by software and hardware TLBs emulation */
79 static inline int pte_is_valid(target_ulong pte0)
81 return pte0 & 0x80000000 ? 1 : 0;
84 static inline void pte_invalidate(target_ulong *pte0)
86 *pte0 &= ~0x80000000;
89 #define PTE_PTEM_MASK 0x7FFFFFBF
90 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
92 static int pp_check(int key, int pp, int nx)
94 int access;
96 /* Compute access rights */
97 access = 0;
98 if (key == 0) {
99 switch (pp) {
100 case 0x0:
101 case 0x1:
102 case 0x2:
103 access |= PAGE_WRITE;
104 /* fall through */
105 case 0x3:
106 access |= PAGE_READ;
107 break;
109 } else {
110 switch (pp) {
111 case 0x0:
112 access = 0;
113 break;
114 case 0x1:
115 case 0x3:
116 access = PAGE_READ;
117 break;
118 case 0x2:
119 access = PAGE_READ | PAGE_WRITE;
120 break;
123 if (nx == 0) {
124 access |= PAGE_EXEC;
127 return access;
130 static int check_prot(int prot, MMUAccessType access_type)
132 return prot & prot_for_access_type(access_type) ? 0 : -2;
135 static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
136 target_ulong pte1, int h,
137 MMUAccessType access_type)
139 target_ulong ptem, mmask;
140 int access, ret, pteh, ptev, pp;
142 ret = -1;
143 /* Check validity and table match */
144 ptev = pte_is_valid(pte0);
145 pteh = (pte0 >> 6) & 1;
146 if (ptev && h == pteh) {
147 /* Check vsid & api */
148 ptem = pte0 & PTE_PTEM_MASK;
149 mmask = PTE_CHECK_MASK;
150 pp = pte1 & 0x00000003;
151 if (ptem == ctx->ptem) {
152 if (ctx->raddr != (hwaddr)-1ULL) {
153 /* all matches should have equal RPN, WIMG & PP */
154 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
155 qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
156 return -3;
159 /* Compute access rights */
160 access = pp_check(ctx->key, pp, ctx->nx);
161 /* Keep the matching PTE information */
162 ctx->raddr = pte1;
163 ctx->prot = access;
164 ret = check_prot(ctx->prot, access_type);
165 if (ret == 0) {
166 /* Access granted */
167 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
168 } else {
169 /* Access right violation */
170 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
175 return ret;
178 static int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
179 int ret, MMUAccessType access_type)
181 int store = 0;
183 /* Update page flags */
184 if (!(*pte1p & 0x00000100)) {
185 /* Update accessed flag */
186 *pte1p |= 0x00000100;
187 store = 1;
189 if (!(*pte1p & 0x00000080)) {
190 if (access_type == MMU_DATA_STORE && ret == 0) {
191 /* Update changed flag */
192 *pte1p |= 0x00000080;
193 store = 1;
194 } else {
195 /* Force page fault for first write access */
196 ctx->prot &= ~PAGE_WRITE;
200 return store;
203 /* Software driven TLB helpers */
204 static inline int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
205 int way, int is_code)
207 int nr;
209 /* Select TLB num in a way from address */
210 nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
211 /* Select TLB way */
212 nr += env->tlb_per_way * way;
213 /* 6xx have separate TLBs for instructions and data */
214 if (is_code && env->id_tlbs == 1) {
215 nr += env->nb_tlb;
218 return nr;
221 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState *env)
223 ppc6xx_tlb_t *tlb;
224 int nr, max;
226 /* LOG_SWTLB("Invalidate all TLBs\n"); */
227 /* Invalidate all defined software TLB */
228 max = env->nb_tlb;
229 if (env->id_tlbs == 1) {
230 max *= 2;
232 for (nr = 0; nr < max; nr++) {
233 tlb = &env->tlb.tlb6[nr];
234 pte_invalidate(&tlb->pte0);
236 tlb_flush(env_cpu(env));
239 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState *env,
240 target_ulong eaddr,
241 int is_code, int match_epn)
243 #if !defined(FLUSH_ALL_TLBS)
244 CPUState *cs = env_cpu(env);
245 ppc6xx_tlb_t *tlb;
246 int way, nr;
248 /* Invalidate ITLB + DTLB, all ways */
249 for (way = 0; way < env->nb_ways; way++) {
250 nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
251 tlb = &env->tlb.tlb6[nr];
252 if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
253 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
254 env->nb_tlb, eaddr);
255 pte_invalidate(&tlb->pte0);
256 tlb_flush_page(cs, tlb->EPN);
259 #else
260 /* XXX: PowerPC specification say this is valid as well */
261 ppc6xx_tlb_invalidate_all(env);
262 #endif
265 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState *env,
266 target_ulong eaddr, int is_code)
268 ppc6xx_tlb_invalidate_virt2(env, eaddr, is_code, 0);
271 static void ppc6xx_tlb_store(CPUPPCState *env, target_ulong EPN, int way,
272 int is_code, target_ulong pte0, target_ulong pte1)
274 ppc6xx_tlb_t *tlb;
275 int nr;
277 nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
278 tlb = &env->tlb.tlb6[nr];
279 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
280 " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
281 /* Invalidate any pending reference in QEMU for this virtual address */
282 ppc6xx_tlb_invalidate_virt2(env, EPN, is_code, 1);
283 tlb->pte0 = pte0;
284 tlb->pte1 = pte1;
285 tlb->EPN = EPN;
286 /* Store last way for LRU mechanism */
287 env->last_way = way;
290 static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
291 target_ulong eaddr, MMUAccessType access_type)
293 ppc6xx_tlb_t *tlb;
294 int nr, best, way;
295 int ret;
297 best = -1;
298 ret = -1; /* No TLB found */
299 for (way = 0; way < env->nb_ways; way++) {
300 nr = ppc6xx_tlb_getnum(env, eaddr, way, access_type == MMU_INST_FETCH);
301 tlb = &env->tlb.tlb6[nr];
302 /* This test "emulates" the PTE index match for hardware TLBs */
303 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
304 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
305 "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
306 pte_is_valid(tlb->pte0) ? "valid" : "inval",
307 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
308 continue;
310 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
311 TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
312 pte_is_valid(tlb->pte0) ? "valid" : "inval",
313 tlb->EPN, eaddr, tlb->pte1,
314 access_type == MMU_DATA_STORE ? 'S' : 'L',
315 access_type == MMU_INST_FETCH ? 'I' : 'D');
316 switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1,
317 0, access_type)) {
318 case -3:
319 /* TLB inconsistency */
320 return -1;
321 case -2:
322 /* Access violation */
323 ret = -2;
324 best = nr;
325 break;
326 case -1:
327 default:
328 /* No match */
329 break;
330 case 0:
331 /* access granted */
333 * XXX: we should go on looping to check all TLBs
334 * consistency but we can speed-up the whole thing as
335 * the result would be undefined if TLBs are not
336 * consistent.
338 ret = 0;
339 best = nr;
340 goto done;
343 if (best != -1) {
344 done:
345 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
346 ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
347 /* Update page flags */
348 pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, access_type);
351 return ret;
354 /* Perform BAT hit & translation */
355 static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
356 int *validp, int *protp, target_ulong *BATu,
357 target_ulong *BATl)
359 target_ulong bl;
360 int pp, valid, prot;
362 bl = (*BATu & 0x00001FFC) << 15;
363 valid = 0;
364 prot = 0;
365 if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
366 ((msr_pr != 0) && (*BATu & 0x00000001))) {
367 valid = 1;
368 pp = *BATl & 0x00000003;
369 if (pp != 0) {
370 prot = PAGE_READ | PAGE_EXEC;
371 if (pp == 0x2) {
372 prot |= PAGE_WRITE;
376 *blp = bl;
377 *validp = valid;
378 *protp = prot;
381 static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
382 target_ulong virtual, MMUAccessType access_type)
384 target_ulong *BATlt, *BATut, *BATu, *BATl;
385 target_ulong BEPIl, BEPIu, bl;
386 int i, valid, prot;
387 int ret = -1;
388 bool ifetch = access_type == MMU_INST_FETCH;
390 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
391 ifetch ? 'I' : 'D', virtual);
392 if (ifetch) {
393 BATlt = env->IBAT[1];
394 BATut = env->IBAT[0];
395 } else {
396 BATlt = env->DBAT[1];
397 BATut = env->DBAT[0];
399 for (i = 0; i < env->nb_BATs; i++) {
400 BATu = &BATut[i];
401 BATl = &BATlt[i];
402 BEPIu = *BATu & 0xF0000000;
403 BEPIl = *BATu & 0x0FFE0000;
404 bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
405 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
406 " BATl " TARGET_FMT_lx "\n", __func__,
407 ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
408 if ((virtual & 0xF0000000) == BEPIu &&
409 ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
410 /* BAT matches */
411 if (valid != 0) {
412 /* Get physical address */
413 ctx->raddr = (*BATl & 0xF0000000) |
414 ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
415 (virtual & 0x0001F000);
416 /* Compute access rights */
417 ctx->prot = prot;
418 ret = check_prot(ctx->prot, access_type);
419 if (ret == 0) {
420 LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
421 i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
422 ctx->prot & PAGE_WRITE ? 'W' : '-');
424 break;
428 if (ret < 0) {
429 #if defined(DEBUG_BATS)
430 if (qemu_log_enabled()) {
431 LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
432 for (i = 0; i < 4; i++) {
433 BATu = &BATut[i];
434 BATl = &BATlt[i];
435 BEPIu = *BATu & 0xF0000000;
436 BEPIl = *BATu & 0x0FFE0000;
437 bl = (*BATu & 0x00001FFC) << 15;
438 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
439 " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
440 TARGET_FMT_lx " " TARGET_FMT_lx "\n",
441 __func__, ifetch ? 'I' : 'D', i, virtual,
442 *BATu, *BATl, BEPIu, BEPIl, bl);
445 #endif
447 /* No hit */
448 return ret;
451 /* Perform segment based translation */
452 static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
453 target_ulong eaddr, MMUAccessType access_type,
454 int type)
456 PowerPCCPU *cpu = env_archcpu(env);
457 hwaddr hash;
458 target_ulong vsid;
459 int ds, pr, target_page_bits;
460 int ret;
461 target_ulong sr, pgidx;
463 pr = msr_pr;
464 ctx->eaddr = eaddr;
466 sr = env->sr[eaddr >> 28];
467 ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
468 ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
469 ds = sr & 0x80000000 ? 1 : 0;
470 ctx->nx = sr & 0x10000000 ? 1 : 0;
471 vsid = sr & 0x00FFFFFF;
472 target_page_bits = TARGET_PAGE_BITS;
473 qemu_log_mask(CPU_LOG_MMU,
474 "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
475 " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
476 " ir=%d dr=%d pr=%d %d t=%d\n",
477 eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
478 (int)msr_dr, pr != 0 ? 1 : 0, access_type == MMU_DATA_STORE, type);
479 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
480 hash = vsid ^ pgidx;
481 ctx->ptem = (vsid << 7) | (pgidx >> 10);
483 qemu_log_mask(CPU_LOG_MMU,
484 "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
485 ctx->key, ds, ctx->nx, vsid);
486 ret = -1;
487 if (!ds) {
488 /* Check if instruction fetch is allowed, if needed */
489 if (type != ACCESS_CODE || ctx->nx == 0) {
490 /* Page address translation */
491 qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx
492 " htab_mask " TARGET_FMT_plx
493 " hash " TARGET_FMT_plx "\n",
494 ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
495 ctx->hash[0] = hash;
496 ctx->hash[1] = ~hash;
498 /* Initialize real address with an invalid value */
499 ctx->raddr = (hwaddr)-1ULL;
500 /* Software TLB search */
501 ret = ppc6xx_tlb_check(env, ctx, eaddr, access_type);
502 #if defined(DUMP_PAGE_TABLES)
503 if (qemu_loglevel_mask(CPU_LOG_MMU)) {
504 CPUState *cs = env_cpu(env);
505 hwaddr curaddr;
506 uint32_t a0, a1, a2, a3;
508 qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
509 "\n", ppc_hash32_hpt_base(cpu),
510 ppc_hash32_hpt_mask(env) + 0x80);
511 for (curaddr = ppc_hash32_hpt_base(cpu);
512 curaddr < (ppc_hash32_hpt_base(cpu)
513 + ppc_hash32_hpt_mask(cpu) + 0x80);
514 curaddr += 16) {
515 a0 = ldl_phys(cs->as, curaddr);
516 a1 = ldl_phys(cs->as, curaddr + 4);
517 a2 = ldl_phys(cs->as, curaddr + 8);
518 a3 = ldl_phys(cs->as, curaddr + 12);
519 if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
520 qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
521 curaddr, a0, a1, a2, a3);
525 #endif
526 } else {
527 qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
528 ret = -3;
530 } else {
531 target_ulong sr;
533 qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
534 /* Direct-store segment : absolutely *BUGGY* for now */
537 * Direct-store implies a 32-bit MMU.
538 * Check the Segment Register's bus unit ID (BUID).
540 sr = env->sr[eaddr >> 28];
541 if ((sr & 0x1FF00000) >> 20 == 0x07f) {
543 * Memory-forced I/O controller interface access
545 * If T=1 and BUID=x'07F', the 601 performs a memory
546 * access to SR[28-31] LA[4-31], bypassing all protection
547 * mechanisms.
549 ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
550 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
551 return 0;
554 switch (type) {
555 case ACCESS_INT:
556 /* Integer load/store : only access allowed */
557 break;
558 case ACCESS_CODE:
559 /* No code fetch is allowed in direct-store areas */
560 return -4;
561 case ACCESS_FLOAT:
562 /* Floating point load/store */
563 return -4;
564 case ACCESS_RES:
565 /* lwarx, ldarx or srwcx. */
566 return -4;
567 case ACCESS_CACHE:
569 * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
571 * Should make the instruction do no-op. As it already do
572 * no-op, it's quite easy :-)
574 ctx->raddr = eaddr;
575 return 0;
576 case ACCESS_EXT:
577 /* eciwx or ecowx */
578 return -4;
579 default:
580 qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need "
581 "address translation\n");
582 return -4;
584 if ((access_type == MMU_DATA_STORE || ctx->key != 1) &&
585 (access_type == MMU_DATA_LOAD || ctx->key != 0)) {
586 ctx->raddr = eaddr;
587 ret = 2;
588 } else {
589 ret = -2;
593 return ret;
596 /* Generic TLB check function for embedded PowerPC implementations */
597 static int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
598 hwaddr *raddrp,
599 target_ulong address, uint32_t pid, int ext,
600 int i)
602 target_ulong mask;
604 /* Check valid flag */
605 if (!(tlb->prot & PAGE_VALID)) {
606 return -1;
608 mask = ~(tlb->size - 1);
609 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
610 " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
611 mask, (uint32_t)tlb->PID, tlb->prot);
612 /* Check PID */
613 if (tlb->PID != 0 && tlb->PID != pid) {
614 return -1;
616 /* Check effective address */
617 if ((address & mask) != tlb->EPN) {
618 return -1;
620 *raddrp = (tlb->RPN & mask) | (address & ~mask);
621 if (ext) {
622 /* Extend the physical address to 36 bits */
623 *raddrp |= (uint64_t)(tlb->RPN & 0xF) << 32;
626 return 0;
629 /* Generic TLB search function for PowerPC embedded implementations */
630 static int ppcemb_tlb_search(CPUPPCState *env, target_ulong address,
631 uint32_t pid)
633 ppcemb_tlb_t *tlb;
634 hwaddr raddr;
635 int i, ret;
637 /* Default return value is no match */
638 ret = -1;
639 for (i = 0; i < env->nb_tlb; i++) {
640 tlb = &env->tlb.tlbe[i];
641 if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
642 ret = i;
643 break;
647 return ret;
650 /* Helpers specific to PowerPC 40x implementations */
651 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState *env)
653 ppcemb_tlb_t *tlb;
654 int i;
656 for (i = 0; i < env->nb_tlb; i++) {
657 tlb = &env->tlb.tlbe[i];
658 tlb->prot &= ~PAGE_VALID;
660 tlb_flush(env_cpu(env));
663 static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
664 target_ulong address,
665 MMUAccessType access_type)
667 ppcemb_tlb_t *tlb;
668 hwaddr raddr;
669 int i, ret, zsel, zpr, pr;
671 ret = -1;
672 raddr = (hwaddr)-1ULL;
673 pr = msr_pr;
674 for (i = 0; i < env->nb_tlb; i++) {
675 tlb = &env->tlb.tlbe[i];
676 if (ppcemb_tlb_check(env, tlb, &raddr, address,
677 env->spr[SPR_40x_PID], 0, i) < 0) {
678 continue;
680 zsel = (tlb->attr >> 4) & 0xF;
681 zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
682 LOG_SWTLB("%s: TLB %d zsel %d zpr %d ty %d attr %08x\n",
683 __func__, i, zsel, zpr, access_type, tlb->attr);
684 /* Check execute enable bit */
685 switch (zpr) {
686 case 0x2:
687 if (pr != 0) {
688 goto check_perms;
690 /* fall through */
691 case 0x3:
692 /* All accesses granted */
693 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
694 ret = 0;
695 break;
696 case 0x0:
697 if (pr != 0) {
698 /* Raise Zone protection fault. */
699 env->spr[SPR_40x_ESR] = 1 << 22;
700 ctx->prot = 0;
701 ret = -2;
702 break;
704 /* fall through */
705 case 0x1:
706 check_perms:
707 /* Check from TLB entry */
708 ctx->prot = tlb->prot;
709 ret = check_prot(ctx->prot, access_type);
710 if (ret == -2) {
711 env->spr[SPR_40x_ESR] = 0;
713 break;
715 if (ret >= 0) {
716 ctx->raddr = raddr;
717 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
718 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
719 ret);
720 return 0;
723 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
724 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
726 return ret;
729 void store_40x_sler(CPUPPCState *env, uint32_t val)
731 /* XXX: TO BE FIXED */
732 if (val != 0x00000000) {
733 cpu_abort(env_cpu(env),
734 "Little-endian regions are not supported by now\n");
736 env->spr[SPR_405_SLER] = val;
739 static int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb,
740 hwaddr *raddr, int *prot, target_ulong address,
741 MMUAccessType access_type, int i)
743 int prot2;
745 if (ppcemb_tlb_check(env, tlb, raddr, address,
746 env->spr[SPR_BOOKE_PID],
747 !env->nb_pids, i) >= 0) {
748 goto found_tlb;
751 if (env->spr[SPR_BOOKE_PID1] &&
752 ppcemb_tlb_check(env, tlb, raddr, address,
753 env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
754 goto found_tlb;
757 if (env->spr[SPR_BOOKE_PID2] &&
758 ppcemb_tlb_check(env, tlb, raddr, address,
759 env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
760 goto found_tlb;
763 LOG_SWTLB("%s: TLB entry not found\n", __func__);
764 return -1;
766 found_tlb:
768 if (msr_pr != 0) {
769 prot2 = tlb->prot & 0xF;
770 } else {
771 prot2 = (tlb->prot >> 4) & 0xF;
774 /* Check the address space */
775 if ((access_type == MMU_INST_FETCH ? msr_ir : msr_dr) != (tlb->attr & 1)) {
776 LOG_SWTLB("%s: AS doesn't match\n", __func__);
777 return -1;
780 *prot = prot2;
781 if (prot2 & prot_for_access_type(access_type)) {
782 LOG_SWTLB("%s: good TLB!\n", __func__);
783 return 0;
786 LOG_SWTLB("%s: no prot match: %x\n", __func__, prot2);
787 return access_type == MMU_INST_FETCH ? -3 : -2;
790 static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
791 target_ulong address,
792 MMUAccessType access_type)
794 ppcemb_tlb_t *tlb;
795 hwaddr raddr;
796 int i, ret;
798 ret = -1;
799 raddr = (hwaddr)-1ULL;
800 for (i = 0; i < env->nb_tlb; i++) {
801 tlb = &env->tlb.tlbe[i];
802 ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address,
803 access_type, i);
804 if (ret != -1) {
805 break;
809 if (ret >= 0) {
810 ctx->raddr = raddr;
811 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
812 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
813 ret);
814 } else {
815 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
816 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
819 return ret;
822 static void booke206_flush_tlb(CPUPPCState *env, int flags,
823 const int check_iprot)
825 int tlb_size;
826 int i, j;
827 ppcmas_tlb_t *tlb = env->tlb.tlbm;
829 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
830 if (flags & (1 << i)) {
831 tlb_size = booke206_tlb_size(env, i);
832 for (j = 0; j < tlb_size; j++) {
833 if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) {
834 tlb[j].mas1 &= ~MAS1_VALID;
838 tlb += booke206_tlb_size(env, i);
841 tlb_flush(env_cpu(env));
844 static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
845 ppcmas_tlb_t *tlb)
847 int tlbm_size;
849 tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
851 return 1024ULL << tlbm_size;
854 /* TLB check function for MAS based SoftTLBs */
855 static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
856 hwaddr *raddrp, target_ulong address,
857 uint32_t pid)
859 hwaddr mask;
860 uint32_t tlb_pid;
862 if (!msr_cm) {
863 /* In 32bit mode we can only address 32bit EAs */
864 address = (uint32_t)address;
867 /* Check valid flag */
868 if (!(tlb->mas1 & MAS1_VALID)) {
869 return -1;
872 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
873 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
874 PRIx64 " mask=0x%" HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%"
875 PRIx32 "\n", __func__, address, pid, tlb->mas1, tlb->mas2, mask,
876 tlb->mas7_3, tlb->mas8);
878 /* Check PID */
879 tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
880 if (tlb_pid != 0 && tlb_pid != pid) {
881 return -1;
884 /* Check effective address */
885 if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
886 return -1;
889 if (raddrp) {
890 *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
893 return 0;
896 static bool is_epid_mmu(int mmu_idx)
898 return mmu_idx == PPC_TLB_EPID_STORE || mmu_idx == PPC_TLB_EPID_LOAD;
901 static uint32_t mmubooke206_esr(int mmu_idx, MMUAccessType access_type)
903 uint32_t esr = 0;
904 if (access_type == MMU_DATA_STORE) {
905 esr |= ESR_ST;
907 if (is_epid_mmu(mmu_idx)) {
908 esr |= ESR_EPID;
910 return esr;
914 * Get EPID register given the mmu_idx. If this is regular load,
915 * construct the EPID access bits from current processor state
917 * Get the effective AS and PR bits and the PID. The PID is returned
918 * only if EPID load is requested, otherwise the caller must detect
919 * the correct EPID. Return true if valid EPID is returned.
921 static bool mmubooke206_get_as(CPUPPCState *env,
922 int mmu_idx, uint32_t *epid_out,
923 bool *as_out, bool *pr_out)
925 if (is_epid_mmu(mmu_idx)) {
926 uint32_t epidr;
927 if (mmu_idx == PPC_TLB_EPID_STORE) {
928 epidr = env->spr[SPR_BOOKE_EPSC];
929 } else {
930 epidr = env->spr[SPR_BOOKE_EPLC];
932 *epid_out = (epidr & EPID_EPID) >> EPID_EPID_SHIFT;
933 *as_out = !!(epidr & EPID_EAS);
934 *pr_out = !!(epidr & EPID_EPR);
935 return true;
936 } else {
937 *as_out = msr_ds;
938 *pr_out = msr_pr;
939 return false;
943 /* Check if the tlb found by hashing really matches */
944 static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
945 hwaddr *raddr, int *prot,
946 target_ulong address,
947 MMUAccessType access_type,
948 int type, int mmu_idx)
950 int ret;
951 int prot2 = 0;
952 uint32_t epid;
953 bool as, pr;
954 bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
956 if (!use_epid) {
957 if (ppcmas_tlb_check(env, tlb, raddr, address,
958 env->spr[SPR_BOOKE_PID]) >= 0) {
959 goto found_tlb;
962 if (env->spr[SPR_BOOKE_PID1] &&
963 ppcmas_tlb_check(env, tlb, raddr, address,
964 env->spr[SPR_BOOKE_PID1]) >= 0) {
965 goto found_tlb;
968 if (env->spr[SPR_BOOKE_PID2] &&
969 ppcmas_tlb_check(env, tlb, raddr, address,
970 env->spr[SPR_BOOKE_PID2]) >= 0) {
971 goto found_tlb;
973 } else {
974 if (ppcmas_tlb_check(env, tlb, raddr, address, epid) >= 0) {
975 goto found_tlb;
979 LOG_SWTLB("%s: TLB entry not found\n", __func__);
980 return -1;
982 found_tlb:
984 if (pr) {
985 if (tlb->mas7_3 & MAS3_UR) {
986 prot2 |= PAGE_READ;
988 if (tlb->mas7_3 & MAS3_UW) {
989 prot2 |= PAGE_WRITE;
991 if (tlb->mas7_3 & MAS3_UX) {
992 prot2 |= PAGE_EXEC;
994 } else {
995 if (tlb->mas7_3 & MAS3_SR) {
996 prot2 |= PAGE_READ;
998 if (tlb->mas7_3 & MAS3_SW) {
999 prot2 |= PAGE_WRITE;
1001 if (tlb->mas7_3 & MAS3_SX) {
1002 prot2 |= PAGE_EXEC;
1006 /* Check the address space and permissions */
1007 if (type == ACCESS_CODE) {
1008 /* There is no way to fetch code using epid load */
1009 assert(!use_epid);
1010 if (msr_ir != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1011 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1012 return -1;
1015 *prot = prot2;
1016 if (prot2 & PAGE_EXEC) {
1017 LOG_SWTLB("%s: good TLB!\n", __func__);
1018 return 0;
1021 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, prot2);
1022 ret = -3;
1023 } else {
1024 if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1025 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1026 return -1;
1029 *prot = prot2;
1030 if (prot2 & (access_type == MMU_DATA_LOAD ? PAGE_READ : PAGE_WRITE)) {
1031 LOG_SWTLB("%s: found TLB!\n", __func__);
1032 return 0;
1035 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, prot2);
1036 ret = -2;
1039 return ret;
1042 static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
1043 target_ulong address,
1044 MMUAccessType access_type,
1045 int type, int mmu_idx)
1047 ppcmas_tlb_t *tlb;
1048 hwaddr raddr;
1049 int i, j, ret;
1051 ret = -1;
1052 raddr = (hwaddr)-1ULL;
1054 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1055 int ways = booke206_tlb_ways(env, i);
1057 for (j = 0; j < ways; j++) {
1058 tlb = booke206_get_tlbm(env, i, address, j);
1059 if (!tlb) {
1060 continue;
1062 ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
1063 access_type, type, mmu_idx);
1064 if (ret != -1) {
1065 goto found_tlb;
1070 found_tlb:
1072 if (ret >= 0) {
1073 ctx->raddr = raddr;
1074 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1075 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1076 ret);
1077 } else {
1078 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1079 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1082 return ret;
1085 static const char *book3e_tsize_to_str[32] = {
1086 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1087 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1088 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1089 "1T", "2T"
1092 static void mmubooke_dump_mmu(CPUPPCState *env)
1094 ppcemb_tlb_t *entry;
1095 int i;
1097 if (kvm_enabled() && !env->kvm_sw_tlb) {
1098 qemu_printf("Cannot access KVM TLB\n");
1099 return;
1102 qemu_printf("\nTLB:\n");
1103 qemu_printf("Effective Physical Size PID Prot "
1104 "Attr\n");
1106 entry = &env->tlb.tlbe[0];
1107 for (i = 0; i < env->nb_tlb; i++, entry++) {
1108 hwaddr ea, pa;
1109 target_ulong mask;
1110 uint64_t size = (uint64_t)entry->size;
1111 char size_buf[20];
1113 /* Check valid flag */
1114 if (!(entry->prot & PAGE_VALID)) {
1115 continue;
1118 mask = ~(entry->size - 1);
1119 ea = entry->EPN & mask;
1120 pa = entry->RPN & mask;
1121 /* Extend the physical address to 36 bits */
1122 pa |= (hwaddr)(entry->RPN & 0xF) << 32;
1123 if (size >= 1 * MiB) {
1124 snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB);
1125 } else {
1126 snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB);
1128 qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
1129 (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
1130 entry->prot, entry->attr);
1135 static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset,
1136 int tlbsize)
1138 ppcmas_tlb_t *entry;
1139 int i;
1141 qemu_printf("\nTLB%d:\n", tlbn);
1142 qemu_printf("Effective Physical Size TID TS SRWX"
1143 " URWX WIMGE U0123\n");
1145 entry = &env->tlb.tlbm[offset];
1146 for (i = 0; i < tlbsize; i++, entry++) {
1147 hwaddr ea, pa, size;
1148 int tsize;
1150 if (!(entry->mas1 & MAS1_VALID)) {
1151 continue;
1154 tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1155 size = 1024ULL << tsize;
1156 ea = entry->mas2 & ~(size - 1);
1157 pa = entry->mas7_3 & ~(size - 1);
1159 qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u S%c%c%c"
1160 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1161 (uint64_t)ea, (uint64_t)pa,
1162 book3e_tsize_to_str[tsize],
1163 (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
1164 (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
1165 entry->mas7_3 & MAS3_SR ? 'R' : '-',
1166 entry->mas7_3 & MAS3_SW ? 'W' : '-',
1167 entry->mas7_3 & MAS3_SX ? 'X' : '-',
1168 entry->mas7_3 & MAS3_UR ? 'R' : '-',
1169 entry->mas7_3 & MAS3_UW ? 'W' : '-',
1170 entry->mas7_3 & MAS3_UX ? 'X' : '-',
1171 entry->mas2 & MAS2_W ? 'W' : '-',
1172 entry->mas2 & MAS2_I ? 'I' : '-',
1173 entry->mas2 & MAS2_M ? 'M' : '-',
1174 entry->mas2 & MAS2_G ? 'G' : '-',
1175 entry->mas2 & MAS2_E ? 'E' : '-',
1176 entry->mas7_3 & MAS3_U0 ? '0' : '-',
1177 entry->mas7_3 & MAS3_U1 ? '1' : '-',
1178 entry->mas7_3 & MAS3_U2 ? '2' : '-',
1179 entry->mas7_3 & MAS3_U3 ? '3' : '-');
1183 static void mmubooke206_dump_mmu(CPUPPCState *env)
1185 int offset = 0;
1186 int i;
1188 if (kvm_enabled() && !env->kvm_sw_tlb) {
1189 qemu_printf("Cannot access KVM TLB\n");
1190 return;
1193 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1194 int size = booke206_tlb_size(env, i);
1196 if (size == 0) {
1197 continue;
1200 mmubooke206_dump_one_tlb(env, i, offset, size);
1201 offset += size;
1205 static void mmu6xx_dump_BATs(CPUPPCState *env, int type)
1207 target_ulong *BATlt, *BATut, *BATu, *BATl;
1208 target_ulong BEPIl, BEPIu, bl;
1209 int i;
1211 switch (type) {
1212 case ACCESS_CODE:
1213 BATlt = env->IBAT[1];
1214 BATut = env->IBAT[0];
1215 break;
1216 default:
1217 BATlt = env->DBAT[1];
1218 BATut = env->DBAT[0];
1219 break;
1222 for (i = 0; i < env->nb_BATs; i++) {
1223 BATu = &BATut[i];
1224 BATl = &BATlt[i];
1225 BEPIu = *BATu & 0xF0000000;
1226 BEPIl = *BATu & 0x0FFE0000;
1227 bl = (*BATu & 0x00001FFC) << 15;
1228 qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
1229 " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
1230 TARGET_FMT_lx " " TARGET_FMT_lx "\n",
1231 type == ACCESS_CODE ? "code" : "data", i,
1232 *BATu, *BATl, BEPIu, BEPIl, bl);
1236 static void mmu6xx_dump_mmu(CPUPPCState *env)
1238 PowerPCCPU *cpu = env_archcpu(env);
1239 ppc6xx_tlb_t *tlb;
1240 target_ulong sr;
1241 int type, way, entry, i;
1243 qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu));
1244 qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu));
1246 qemu_printf("\nSegment registers:\n");
1247 for (i = 0; i < 32; i++) {
1248 sr = env->sr[i];
1249 if (sr & 0x80000000) {
1250 qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1251 "CNTLR_SPEC=0x%05x\n", i,
1252 sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
1253 sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF),
1254 (uint32_t)(sr & 0xFFFFF));
1255 } else {
1256 qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i,
1257 sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
1258 sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0,
1259 (uint32_t)(sr & 0x00FFFFFF));
1263 qemu_printf("\nBATs:\n");
1264 mmu6xx_dump_BATs(env, ACCESS_INT);
1265 mmu6xx_dump_BATs(env, ACCESS_CODE);
1267 if (env->id_tlbs != 1) {
1268 qemu_printf("ERROR: 6xx MMU should have separated TLB"
1269 " for code and data\n");
1272 qemu_printf("\nTLBs [EPN EPN + SIZE]\n");
1274 for (type = 0; type < 2; type++) {
1275 for (way = 0; way < env->nb_ways; way++) {
1276 for (entry = env->nb_tlb * type + env->tlb_per_way * way;
1277 entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1));
1278 entry++) {
1280 tlb = &env->tlb.tlb6[entry];
1281 qemu_printf("%s TLB %02d/%02d way:%d %s ["
1282 TARGET_FMT_lx " " TARGET_FMT_lx "]\n",
1283 type ? "code" : "data", entry % env->nb_tlb,
1284 env->nb_tlb, way,
1285 pte_is_valid(tlb->pte0) ? "valid" : "inval",
1286 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE);
1292 void dump_mmu(CPUPPCState *env)
1294 switch (env->mmu_model) {
1295 case POWERPC_MMU_BOOKE:
1296 mmubooke_dump_mmu(env);
1297 break;
1298 case POWERPC_MMU_BOOKE206:
1299 mmubooke206_dump_mmu(env);
1300 break;
1301 case POWERPC_MMU_SOFT_6xx:
1302 case POWERPC_MMU_SOFT_74xx:
1303 mmu6xx_dump_mmu(env);
1304 break;
1305 #if defined(TARGET_PPC64)
1306 case POWERPC_MMU_64B:
1307 case POWERPC_MMU_2_03:
1308 case POWERPC_MMU_2_06:
1309 case POWERPC_MMU_2_07:
1310 dump_slb(env_archcpu(env));
1311 break;
1312 case POWERPC_MMU_3_00:
1313 if (ppc64_v3_radix(env_archcpu(env))) {
1314 qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n",
1315 __func__);
1316 } else {
1317 dump_slb(env_archcpu(env));
1319 break;
1320 #endif
1321 default:
1322 qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
1326 static int check_physical(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1327 MMUAccessType access_type)
1329 int in_plb, ret;
1331 ctx->raddr = eaddr;
1332 ctx->prot = PAGE_READ | PAGE_EXEC;
1333 ret = 0;
1334 switch (env->mmu_model) {
1335 case POWERPC_MMU_SOFT_6xx:
1336 case POWERPC_MMU_SOFT_74xx:
1337 case POWERPC_MMU_SOFT_4xx:
1338 case POWERPC_MMU_REAL:
1339 case POWERPC_MMU_BOOKE:
1340 ctx->prot |= PAGE_WRITE;
1341 break;
1343 case POWERPC_MMU_SOFT_4xx_Z:
1344 if (unlikely(msr_pe != 0)) {
1346 * 403 family add some particular protections, using
1347 * PBL/PBU registers for accesses with no translation.
1349 in_plb =
1350 /* Check PLB validity */
1351 (env->pb[0] < env->pb[1] &&
1352 /* and address in plb area */
1353 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1354 (env->pb[2] < env->pb[3] &&
1355 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1356 if (in_plb ^ msr_px) {
1357 /* Access in protected area */
1358 if (access_type == MMU_DATA_STORE) {
1359 /* Access is not allowed */
1360 ret = -2;
1362 } else {
1363 /* Read-write access is allowed */
1364 ctx->prot |= PAGE_WRITE;
1367 break;
1369 default:
1370 /* Caller's checks mean we should never get here for other models */
1371 abort();
1372 return -1;
1375 return ret;
1378 static int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
1379 target_ulong eaddr,
1380 MMUAccessType access_type, int type,
1381 int mmu_idx)
1383 int ret = -1;
1384 bool real_mode = (type == ACCESS_CODE && msr_ir == 0)
1385 || (type != ACCESS_CODE && msr_dr == 0);
1387 switch (env->mmu_model) {
1388 case POWERPC_MMU_SOFT_6xx:
1389 case POWERPC_MMU_SOFT_74xx:
1390 if (real_mode) {
1391 ret = check_physical(env, ctx, eaddr, access_type);
1392 } else {
1393 /* Try to find a BAT */
1394 if (env->nb_BATs != 0) {
1395 ret = get_bat_6xx_tlb(env, ctx, eaddr, access_type);
1397 if (ret < 0) {
1398 /* We didn't match any BAT entry or don't have BATs */
1399 ret = get_segment_6xx_tlb(env, ctx, eaddr, access_type, type);
1402 break;
1404 case POWERPC_MMU_SOFT_4xx:
1405 case POWERPC_MMU_SOFT_4xx_Z:
1406 if (real_mode) {
1407 ret = check_physical(env, ctx, eaddr, access_type);
1408 } else {
1409 ret = mmu40x_get_physical_address(env, ctx, eaddr, access_type);
1411 break;
1412 case POWERPC_MMU_BOOKE:
1413 ret = mmubooke_get_physical_address(env, ctx, eaddr, access_type);
1414 break;
1415 case POWERPC_MMU_BOOKE206:
1416 ret = mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
1417 type, mmu_idx);
1418 break;
1419 case POWERPC_MMU_MPC8xx:
1420 /* XXX: TODO */
1421 cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
1422 break;
1423 case POWERPC_MMU_REAL:
1424 if (real_mode) {
1425 ret = check_physical(env, ctx, eaddr, access_type);
1426 } else {
1427 cpu_abort(env_cpu(env),
1428 "PowerPC in real mode do not do any translation\n");
1430 return -1;
1431 default:
1432 cpu_abort(env_cpu(env), "Unknown or invalid MMU model\n");
1433 return -1;
1436 return ret;
1439 static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
1440 target_ulong eaddr, MMUAccessType access_type,
1441 int type)
1443 return get_physical_address_wtlb(env, ctx, eaddr, access_type, type, 0);
1446 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
1448 PowerPCCPU *cpu = POWERPC_CPU(cs);
1449 CPUPPCState *env = &cpu->env;
1450 mmu_ctx_t ctx;
1452 switch (env->mmu_model) {
1453 #if defined(TARGET_PPC64)
1454 case POWERPC_MMU_64B:
1455 case POWERPC_MMU_2_03:
1456 case POWERPC_MMU_2_06:
1457 case POWERPC_MMU_2_07:
1458 return ppc_hash64_get_phys_page_debug(cpu, addr);
1459 case POWERPC_MMU_3_00:
1460 return ppc64_v3_get_phys_page_debug(cpu, addr);
1461 #endif
1463 case POWERPC_MMU_32B:
1464 case POWERPC_MMU_601:
1465 return ppc_hash32_get_phys_page_debug(cpu, addr);
1467 default:
1471 if (unlikely(get_physical_address(env, &ctx, addr, MMU_DATA_LOAD,
1472 ACCESS_INT) != 0)) {
1475 * Some MMUs have separate TLBs for code and data. If we only
1476 * try an ACCESS_INT, we may not be able to read instructions
1477 * mapped by code TLBs, so we also try a ACCESS_CODE.
1479 if (unlikely(get_physical_address(env, &ctx, addr, MMU_INST_FETCH,
1480 ACCESS_CODE) != 0)) {
1481 return -1;
1485 return ctx.raddr & TARGET_PAGE_MASK;
1488 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
1489 MMUAccessType access_type, int mmu_idx)
1491 uint32_t epid;
1492 bool as, pr;
1493 uint32_t missed_tid = 0;
1494 bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
1496 if (access_type == MMU_INST_FETCH) {
1497 as = msr_ir;
1499 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1500 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1501 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1502 env->spr[SPR_BOOKE_MAS3] = 0;
1503 env->spr[SPR_BOOKE_MAS6] = 0;
1504 env->spr[SPR_BOOKE_MAS7] = 0;
1506 /* AS */
1507 if (as) {
1508 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1509 env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1512 env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1513 env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1515 if (!use_epid) {
1516 switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1517 case MAS4_TIDSELD_PID0:
1518 missed_tid = env->spr[SPR_BOOKE_PID];
1519 break;
1520 case MAS4_TIDSELD_PID1:
1521 missed_tid = env->spr[SPR_BOOKE_PID1];
1522 break;
1523 case MAS4_TIDSELD_PID2:
1524 missed_tid = env->spr[SPR_BOOKE_PID2];
1525 break;
1527 env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1528 } else {
1529 missed_tid = epid;
1530 env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
1532 env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
1535 /* next victim logic */
1536 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1537 env->last_way++;
1538 env->last_way &= booke206_tlb_ways(env, 0) - 1;
1539 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1542 /* Perform address translation */
1543 static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
1544 MMUAccessType access_type, int mmu_idx)
1546 CPUState *cs = env_cpu(env);
1547 PowerPCCPU *cpu = POWERPC_CPU(cs);
1548 mmu_ctx_t ctx;
1549 int type;
1550 int ret = 0;
1552 if (access_type == MMU_INST_FETCH) {
1553 /* code access */
1554 type = ACCESS_CODE;
1555 } else {
1556 /* data access */
1557 type = env->access_type;
1559 ret = get_physical_address_wtlb(env, &ctx, address, access_type,
1560 type, mmu_idx);
1561 if (ret == 0) {
1562 tlb_set_page(cs, address & TARGET_PAGE_MASK,
1563 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1564 mmu_idx, TARGET_PAGE_SIZE);
1565 ret = 0;
1566 } else if (ret < 0) {
1567 LOG_MMU_STATE(cs);
1568 if (type == ACCESS_CODE) {
1569 switch (ret) {
1570 case -1:
1571 /* No matches in page tables or TLB */
1572 switch (env->mmu_model) {
1573 case POWERPC_MMU_SOFT_6xx:
1574 cs->exception_index = POWERPC_EXCP_IFTLB;
1575 env->error_code = 1 << 18;
1576 env->spr[SPR_IMISS] = address;
1577 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1578 goto tlb_miss;
1579 case POWERPC_MMU_SOFT_74xx:
1580 cs->exception_index = POWERPC_EXCP_IFTLB;
1581 goto tlb_miss_74xx;
1582 case POWERPC_MMU_SOFT_4xx:
1583 case POWERPC_MMU_SOFT_4xx_Z:
1584 cs->exception_index = POWERPC_EXCP_ITLB;
1585 env->error_code = 0;
1586 env->spr[SPR_40x_DEAR] = address;
1587 env->spr[SPR_40x_ESR] = 0x00000000;
1588 break;
1589 case POWERPC_MMU_BOOKE206:
1590 booke206_update_mas_tlb_miss(env, address, 2, mmu_idx);
1591 /* fall through */
1592 case POWERPC_MMU_BOOKE:
1593 cs->exception_index = POWERPC_EXCP_ITLB;
1594 env->error_code = 0;
1595 env->spr[SPR_BOOKE_DEAR] = address;
1596 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, MMU_DATA_LOAD);
1597 return -1;
1598 case POWERPC_MMU_MPC8xx:
1599 /* XXX: TODO */
1600 cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
1601 break;
1602 case POWERPC_MMU_REAL:
1603 cpu_abort(cs, "PowerPC in real mode should never raise "
1604 "any MMU exceptions\n");
1605 return -1;
1606 default:
1607 cpu_abort(cs, "Unknown or invalid MMU model\n");
1608 return -1;
1610 break;
1611 case -2:
1612 /* Access rights violation */
1613 cs->exception_index = POWERPC_EXCP_ISI;
1614 env->error_code = 0x08000000;
1615 break;
1616 case -3:
1617 /* No execute protection violation */
1618 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1619 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1620 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1622 cs->exception_index = POWERPC_EXCP_ISI;
1623 env->error_code = 0x10000000;
1624 break;
1625 case -4:
1626 /* Direct store exception */
1627 /* No code fetch is allowed in direct-store areas */
1628 cs->exception_index = POWERPC_EXCP_ISI;
1629 env->error_code = 0x10000000;
1630 break;
1632 } else {
1633 switch (ret) {
1634 case -1:
1635 /* No matches in page tables or TLB */
1636 switch (env->mmu_model) {
1637 case POWERPC_MMU_SOFT_6xx:
1638 if (access_type == MMU_DATA_STORE) {
1639 cs->exception_index = POWERPC_EXCP_DSTLB;
1640 env->error_code = 1 << 16;
1641 } else {
1642 cs->exception_index = POWERPC_EXCP_DLTLB;
1643 env->error_code = 0;
1645 env->spr[SPR_DMISS] = address;
1646 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1647 tlb_miss:
1648 env->error_code |= ctx.key << 19;
1649 env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
1650 get_pteg_offset32(cpu, ctx.hash[0]);
1651 env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
1652 get_pteg_offset32(cpu, ctx.hash[1]);
1653 break;
1654 case POWERPC_MMU_SOFT_74xx:
1655 if (access_type == MMU_DATA_STORE) {
1656 cs->exception_index = POWERPC_EXCP_DSTLB;
1657 } else {
1658 cs->exception_index = POWERPC_EXCP_DLTLB;
1660 tlb_miss_74xx:
1661 /* Implement LRU algorithm */
1662 env->error_code = ctx.key << 19;
1663 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1664 ((env->last_way + 1) & (env->nb_ways - 1));
1665 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1666 break;
1667 case POWERPC_MMU_SOFT_4xx:
1668 case POWERPC_MMU_SOFT_4xx_Z:
1669 cs->exception_index = POWERPC_EXCP_DTLB;
1670 env->error_code = 0;
1671 env->spr[SPR_40x_DEAR] = address;
1672 if (access_type == MMU_DATA_STORE) {
1673 env->spr[SPR_40x_ESR] = 0x00800000;
1674 } else {
1675 env->spr[SPR_40x_ESR] = 0x00000000;
1677 break;
1678 case POWERPC_MMU_MPC8xx:
1679 /* XXX: TODO */
1680 cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
1681 break;
1682 case POWERPC_MMU_BOOKE206:
1683 booke206_update_mas_tlb_miss(env, address, access_type, mmu_idx);
1684 /* fall through */
1685 case POWERPC_MMU_BOOKE:
1686 cs->exception_index = POWERPC_EXCP_DTLB;
1687 env->error_code = 0;
1688 env->spr[SPR_BOOKE_DEAR] = address;
1689 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
1690 return -1;
1691 case POWERPC_MMU_REAL:
1692 cpu_abort(cs, "PowerPC in real mode should never raise "
1693 "any MMU exceptions\n");
1694 return -1;
1695 default:
1696 cpu_abort(cs, "Unknown or invalid MMU model\n");
1697 return -1;
1699 break;
1700 case -2:
1701 /* Access rights violation */
1702 cs->exception_index = POWERPC_EXCP_DSI;
1703 env->error_code = 0;
1704 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1705 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1706 env->spr[SPR_40x_DEAR] = address;
1707 if (access_type == MMU_DATA_STORE) {
1708 env->spr[SPR_40x_ESR] |= 0x00800000;
1710 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1711 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1712 env->spr[SPR_BOOKE_DEAR] = address;
1713 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
1714 } else {
1715 env->spr[SPR_DAR] = address;
1716 if (access_type == MMU_DATA_STORE) {
1717 env->spr[SPR_DSISR] = 0x0A000000;
1718 } else {
1719 env->spr[SPR_DSISR] = 0x08000000;
1722 break;
1723 case -4:
1724 /* Direct store exception */
1725 switch (type) {
1726 case ACCESS_FLOAT:
1727 /* Floating point load/store */
1728 cs->exception_index = POWERPC_EXCP_ALIGN;
1729 env->error_code = POWERPC_EXCP_ALIGN_FP;
1730 env->spr[SPR_DAR] = address;
1731 break;
1732 case ACCESS_RES:
1733 /* lwarx, ldarx or stwcx. */
1734 cs->exception_index = POWERPC_EXCP_DSI;
1735 env->error_code = 0;
1736 env->spr[SPR_DAR] = address;
1737 if (access_type == MMU_DATA_STORE) {
1738 env->spr[SPR_DSISR] = 0x06000000;
1739 } else {
1740 env->spr[SPR_DSISR] = 0x04000000;
1742 break;
1743 case ACCESS_EXT:
1744 /* eciwx or ecowx */
1745 cs->exception_index = POWERPC_EXCP_DSI;
1746 env->error_code = 0;
1747 env->spr[SPR_DAR] = address;
1748 if (access_type == MMU_DATA_STORE) {
1749 env->spr[SPR_DSISR] = 0x06100000;
1750 } else {
1751 env->spr[SPR_DSISR] = 0x04100000;
1753 break;
1754 default:
1755 printf("DSI: invalid exception (%d)\n", ret);
1756 cs->exception_index = POWERPC_EXCP_PROGRAM;
1757 env->error_code =
1758 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1759 env->spr[SPR_DAR] = address;
1760 break;
1762 break;
1765 ret = 1;
1768 return ret;
1771 /*****************************************************************************/
1772 /* BATs management */
1773 #if !defined(FLUSH_ALL_TLBS)
1774 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1775 target_ulong mask)
1777 CPUState *cs = env_cpu(env);
1778 target_ulong base, end, page;
1780 base = BATu & ~0x0001FFFF;
1781 end = base + mask + 0x00020000;
1782 if (((end - base) >> TARGET_PAGE_BITS) > 1024) {
1783 /* Flushing 1024 4K pages is slower than a complete flush */
1784 LOG_BATS("Flush all BATs\n");
1785 tlb_flush(cs);
1786 LOG_BATS("Flush done\n");
1787 return;
1789 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1790 TARGET_FMT_lx ")\n", base, end, mask);
1791 for (page = base; page != end; page += TARGET_PAGE_SIZE) {
1792 tlb_flush_page(cs, page);
1794 LOG_BATS("Flush done\n");
1796 #endif
1798 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1799 target_ulong value)
1801 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1802 nr, ul == 0 ? 'u' : 'l', value, env->nip);
1805 void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1807 target_ulong mask;
1808 #if defined(FLUSH_ALL_TLBS)
1809 PowerPCCPU *cpu = env_archcpu(env);
1810 #endif
1812 dump_store_bat(env, 'I', 0, nr, value);
1813 if (env->IBAT[0][nr] != value) {
1814 mask = (value << 15) & 0x0FFE0000UL;
1815 #if !defined(FLUSH_ALL_TLBS)
1816 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1817 #endif
1819 * When storing valid upper BAT, mask BEPI and BRPN and
1820 * invalidate all TLBs covered by this BAT
1822 mask = (value << 15) & 0x0FFE0000UL;
1823 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1824 (value & ~0x0001FFFFUL & ~mask);
1825 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1826 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1827 #if !defined(FLUSH_ALL_TLBS)
1828 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1829 #else
1830 tlb_flush(env_cpu(env));
1831 #endif
1835 void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1837 dump_store_bat(env, 'I', 1, nr, value);
1838 env->IBAT[1][nr] = value;
1841 void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1843 target_ulong mask;
1844 #if defined(FLUSH_ALL_TLBS)
1845 PowerPCCPU *cpu = env_archcpu(env);
1846 #endif
1848 dump_store_bat(env, 'D', 0, nr, value);
1849 if (env->DBAT[0][nr] != value) {
1851 * When storing valid upper BAT, mask BEPI and BRPN and
1852 * invalidate all TLBs covered by this BAT
1854 mask = (value << 15) & 0x0FFE0000UL;
1855 #if !defined(FLUSH_ALL_TLBS)
1856 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1857 #endif
1858 mask = (value << 15) & 0x0FFE0000UL;
1859 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1860 (value & ~0x0001FFFFUL & ~mask);
1861 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1862 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1863 #if !defined(FLUSH_ALL_TLBS)
1864 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1865 #else
1866 tlb_flush(env_cpu(env));
1867 #endif
1871 void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1873 dump_store_bat(env, 'D', 1, nr, value);
1874 env->DBAT[1][nr] = value;
1877 void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
1879 target_ulong mask;
1880 #if defined(FLUSH_ALL_TLBS)
1881 PowerPCCPU *cpu = env_archcpu(env);
1882 int do_inval;
1883 #endif
1885 dump_store_bat(env, 'I', 0, nr, value);
1886 if (env->IBAT[0][nr] != value) {
1887 #if defined(FLUSH_ALL_TLBS)
1888 do_inval = 0;
1889 #endif
1890 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1891 if (env->IBAT[1][nr] & 0x40) {
1892 /* Invalidate BAT only if it is valid */
1893 #if !defined(FLUSH_ALL_TLBS)
1894 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1895 #else
1896 do_inval = 1;
1897 #endif
1900 * When storing valid upper BAT, mask BEPI and BRPN and
1901 * invalidate all TLBs covered by this BAT
1903 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1904 (value & ~0x0001FFFFUL & ~mask);
1905 env->DBAT[0][nr] = env->IBAT[0][nr];
1906 if (env->IBAT[1][nr] & 0x40) {
1907 #if !defined(FLUSH_ALL_TLBS)
1908 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1909 #else
1910 do_inval = 1;
1911 #endif
1913 #if defined(FLUSH_ALL_TLBS)
1914 if (do_inval) {
1915 tlb_flush(env_cpu(env));
1917 #endif
1921 void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
1923 #if !defined(FLUSH_ALL_TLBS)
1924 target_ulong mask;
1925 #else
1926 PowerPCCPU *cpu = env_archcpu(env);
1927 int do_inval;
1928 #endif
1930 dump_store_bat(env, 'I', 1, nr, value);
1931 if (env->IBAT[1][nr] != value) {
1932 #if defined(FLUSH_ALL_TLBS)
1933 do_inval = 0;
1934 #endif
1935 if (env->IBAT[1][nr] & 0x40) {
1936 #if !defined(FLUSH_ALL_TLBS)
1937 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1938 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1939 #else
1940 do_inval = 1;
1941 #endif
1943 if (value & 0x40) {
1944 #if !defined(FLUSH_ALL_TLBS)
1945 mask = (value << 17) & 0x0FFE0000UL;
1946 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1947 #else
1948 do_inval = 1;
1949 #endif
1951 env->IBAT[1][nr] = value;
1952 env->DBAT[1][nr] = value;
1953 #if defined(FLUSH_ALL_TLBS)
1954 if (do_inval) {
1955 tlb_flush(env_cpu(env));
1957 #endif
1961 /*****************************************************************************/
1962 /* TLB management */
1963 void ppc_tlb_invalidate_all(CPUPPCState *env)
1965 #if defined(TARGET_PPC64)
1966 if (mmu_is_64bit(env->mmu_model)) {
1967 env->tlb_need_flush = 0;
1968 tlb_flush(env_cpu(env));
1969 } else
1970 #endif /* defined(TARGET_PPC64) */
1971 switch (env->mmu_model) {
1972 case POWERPC_MMU_SOFT_6xx:
1973 case POWERPC_MMU_SOFT_74xx:
1974 ppc6xx_tlb_invalidate_all(env);
1975 break;
1976 case POWERPC_MMU_SOFT_4xx:
1977 case POWERPC_MMU_SOFT_4xx_Z:
1978 ppc4xx_tlb_invalidate_all(env);
1979 break;
1980 case POWERPC_MMU_REAL:
1981 cpu_abort(env_cpu(env), "No TLB for PowerPC 4xx in real mode\n");
1982 break;
1983 case POWERPC_MMU_MPC8xx:
1984 /* XXX: TODO */
1985 cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
1986 break;
1987 case POWERPC_MMU_BOOKE:
1988 tlb_flush(env_cpu(env));
1989 break;
1990 case POWERPC_MMU_BOOKE206:
1991 booke206_flush_tlb(env, -1, 0);
1992 break;
1993 case POWERPC_MMU_32B:
1994 case POWERPC_MMU_601:
1995 env->tlb_need_flush = 0;
1996 tlb_flush(env_cpu(env));
1997 break;
1998 default:
1999 /* XXX: TODO */
2000 cpu_abort(env_cpu(env), "Unknown MMU model %x\n", env->mmu_model);
2001 break;
2005 void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
2007 #if !defined(FLUSH_ALL_TLBS)
2008 addr &= TARGET_PAGE_MASK;
2009 #if defined(TARGET_PPC64)
2010 if (mmu_is_64bit(env->mmu_model)) {
2011 /* tlbie invalidate TLBs for all segments */
2013 * XXX: given the fact that there are too many segments to invalidate,
2014 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
2015 * we just invalidate all TLBs
2017 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2018 } else
2019 #endif /* defined(TARGET_PPC64) */
2020 switch (env->mmu_model) {
2021 case POWERPC_MMU_SOFT_6xx:
2022 case POWERPC_MMU_SOFT_74xx:
2023 ppc6xx_tlb_invalidate_virt(env, addr, 0);
2024 if (env->id_tlbs == 1) {
2025 ppc6xx_tlb_invalidate_virt(env, addr, 1);
2027 break;
2028 case POWERPC_MMU_32B:
2029 case POWERPC_MMU_601:
2031 * Actual CPUs invalidate entire congruence classes based on
2032 * the geometry of their TLBs and some OSes take that into
2033 * account, we just mark the TLB to be flushed later (context
2034 * synchronizing event or sync instruction on 32-bit).
2036 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2037 break;
2038 default:
2039 /* Should never reach here with other MMU models */
2040 assert(0);
2042 #else
2043 ppc_tlb_invalidate_all(env);
2044 #endif
2047 /*****************************************************************************/
2048 /* Special registers manipulation */
2049 #if defined(TARGET_PPC64)
2050 void ppc_store_ptcr(CPUPPCState *env, target_ulong value)
2052 PowerPCCPU *cpu = env_archcpu(env);
2053 target_ulong ptcr_mask = PTCR_PATB | PTCR_PATS;
2054 target_ulong patbsize = value & PTCR_PATS;
2056 qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
2058 assert(!cpu->vhyp);
2059 assert(env->mmu_model & POWERPC_MMU_3_00);
2061 if (value & ~ptcr_mask) {
2062 error_report("Invalid bits 0x"TARGET_FMT_lx" set in PTCR",
2063 value & ~ptcr_mask);
2064 value &= ptcr_mask;
2067 if (patbsize > 24) {
2068 error_report("Invalid Partition Table size 0x" TARGET_FMT_lx
2069 " stored in PTCR", patbsize);
2070 return;
2073 env->spr[SPR_PTCR] = value;
2076 #endif /* defined(TARGET_PPC64) */
2078 /* Segment registers load and store */
2079 target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
2081 #if defined(TARGET_PPC64)
2082 if (mmu_is_64bit(env->mmu_model)) {
2083 /* XXX */
2084 return 0;
2086 #endif
2087 return env->sr[sr_num];
2090 void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
2092 qemu_log_mask(CPU_LOG_MMU,
2093 "%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2094 (int)srnum, value, env->sr[srnum]);
2095 #if defined(TARGET_PPC64)
2096 if (mmu_is_64bit(env->mmu_model)) {
2097 PowerPCCPU *cpu = env_archcpu(env);
2098 uint64_t esid, vsid;
2100 /* ESID = srnum */
2101 esid = ((uint64_t)(srnum & 0xf) << 28) | SLB_ESID_V;
2103 /* VSID = VSID */
2104 vsid = (value & 0xfffffff) << 12;
2105 /* flags = flags */
2106 vsid |= ((value >> 27) & 0xf) << 8;
2108 ppc_store_slb(cpu, srnum, esid, vsid);
2109 } else
2110 #endif
2111 if (env->sr[srnum] != value) {
2112 env->sr[srnum] = value;
2114 * Invalidating 256MB of virtual memory in 4kB pages is way
2115 * longer than flushing the whole TLB.
2117 #if !defined(FLUSH_ALL_TLBS) && 0
2119 target_ulong page, end;
2120 /* Invalidate 256 MB of virtual memory */
2121 page = (16 << 20) * srnum;
2122 end = page + (16 << 20);
2123 for (; page != end; page += TARGET_PAGE_SIZE) {
2124 tlb_flush_page(env_cpu(env), page);
2127 #else
2128 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2129 #endif
2133 /* TLB management */
2134 void helper_tlbia(CPUPPCState *env)
2136 ppc_tlb_invalidate_all(env);
2139 void helper_tlbie(CPUPPCState *env, target_ulong addr)
2141 ppc_tlb_invalidate_one(env, addr);
2144 void helper_tlbiva(CPUPPCState *env, target_ulong addr)
2146 /* tlbiva instruction only exists on BookE */
2147 assert(env->mmu_model == POWERPC_MMU_BOOKE);
2148 /* XXX: TODO */
2149 cpu_abort(env_cpu(env), "BookE MMU model is not implemented\n");
2152 /* Software driven TLBs management */
2153 /* PowerPC 602/603 software TLB load instructions helpers */
2154 static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2156 target_ulong RPN, CMP, EPN;
2157 int way;
2159 RPN = env->spr[SPR_RPA];
2160 if (is_code) {
2161 CMP = env->spr[SPR_ICMP];
2162 EPN = env->spr[SPR_IMISS];
2163 } else {
2164 CMP = env->spr[SPR_DCMP];
2165 EPN = env->spr[SPR_DMISS];
2167 way = (env->spr[SPR_SRR1] >> 17) & 1;
2168 (void)EPN; /* avoid a compiler warning */
2169 LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2170 " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2171 RPN, way);
2172 /* Store this TLB */
2173 ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2174 way, is_code, CMP, RPN);
2177 void helper_6xx_tlbd(CPUPPCState *env, target_ulong EPN)
2179 do_6xx_tlb(env, EPN, 0);
2182 void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
2184 do_6xx_tlb(env, EPN, 1);
2187 /* PowerPC 74xx software TLB load instructions helpers */
2188 static void do_74xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2190 target_ulong RPN, CMP, EPN;
2191 int way;
2193 RPN = env->spr[SPR_PTELO];
2194 CMP = env->spr[SPR_PTEHI];
2195 EPN = env->spr[SPR_TLBMISS] & ~0x3;
2196 way = env->spr[SPR_TLBMISS] & 0x3;
2197 (void)EPN; /* avoid a compiler warning */
2198 LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2199 " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2200 RPN, way);
2201 /* Store this TLB */
2202 ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2203 way, is_code, CMP, RPN);
2206 void helper_74xx_tlbd(CPUPPCState *env, target_ulong EPN)
2208 do_74xx_tlb(env, EPN, 0);
2211 void helper_74xx_tlbi(CPUPPCState *env, target_ulong EPN)
2213 do_74xx_tlb(env, EPN, 1);
2216 /*****************************************************************************/
2217 /* PowerPC 601 specific instructions (POWER bridge) */
2219 target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
2221 mmu_ctx_t ctx;
2222 int nb_BATs;
2223 target_ulong ret = 0;
2226 * We don't have to generate many instances of this instruction,
2227 * as rac is supervisor only.
2229 * XXX: FIX THIS: Pretend we have no BAT
2231 nb_BATs = env->nb_BATs;
2232 env->nb_BATs = 0;
2233 if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) {
2234 ret = ctx.raddr;
2236 env->nb_BATs = nb_BATs;
2237 return ret;
2240 static inline target_ulong booke_tlb_to_page_size(int size)
2242 return 1024 << (2 * size);
2245 static inline int booke_page_size_to_tlb(target_ulong page_size)
2247 int size;
2249 switch (page_size) {
2250 case 0x00000400UL:
2251 size = 0x0;
2252 break;
2253 case 0x00001000UL:
2254 size = 0x1;
2255 break;
2256 case 0x00004000UL:
2257 size = 0x2;
2258 break;
2259 case 0x00010000UL:
2260 size = 0x3;
2261 break;
2262 case 0x00040000UL:
2263 size = 0x4;
2264 break;
2265 case 0x00100000UL:
2266 size = 0x5;
2267 break;
2268 case 0x00400000UL:
2269 size = 0x6;
2270 break;
2271 case 0x01000000UL:
2272 size = 0x7;
2273 break;
2274 case 0x04000000UL:
2275 size = 0x8;
2276 break;
2277 case 0x10000000UL:
2278 size = 0x9;
2279 break;
2280 case 0x40000000UL:
2281 size = 0xA;
2282 break;
2283 #if defined(TARGET_PPC64)
2284 case 0x000100000000ULL:
2285 size = 0xB;
2286 break;
2287 case 0x000400000000ULL:
2288 size = 0xC;
2289 break;
2290 case 0x001000000000ULL:
2291 size = 0xD;
2292 break;
2293 case 0x004000000000ULL:
2294 size = 0xE;
2295 break;
2296 case 0x010000000000ULL:
2297 size = 0xF;
2298 break;
2299 #endif
2300 default:
2301 size = -1;
2302 break;
2305 return size;
2308 /* Helpers for 4xx TLB management */
2309 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2311 #define PPC4XX_TLBHI_V 0x00000040
2312 #define PPC4XX_TLBHI_E 0x00000020
2313 #define PPC4XX_TLBHI_SIZE_MIN 0
2314 #define PPC4XX_TLBHI_SIZE_MAX 7
2315 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2316 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2317 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2319 #define PPC4XX_TLBLO_EX 0x00000200
2320 #define PPC4XX_TLBLO_WR 0x00000100
2321 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2322 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2324 target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry)
2326 ppcemb_tlb_t *tlb;
2327 target_ulong ret;
2328 int size;
2330 entry &= PPC4XX_TLB_ENTRY_MASK;
2331 tlb = &env->tlb.tlbe[entry];
2332 ret = tlb->EPN;
2333 if (tlb->prot & PAGE_VALID) {
2334 ret |= PPC4XX_TLBHI_V;
2336 size = booke_page_size_to_tlb(tlb->size);
2337 if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) {
2338 size = PPC4XX_TLBHI_SIZE_DEFAULT;
2340 ret |= size << PPC4XX_TLBHI_SIZE_SHIFT;
2341 env->spr[SPR_40x_PID] = tlb->PID;
2342 return ret;
2345 target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, target_ulong entry)
2347 ppcemb_tlb_t *tlb;
2348 target_ulong ret;
2350 entry &= PPC4XX_TLB_ENTRY_MASK;
2351 tlb = &env->tlb.tlbe[entry];
2352 ret = tlb->RPN;
2353 if (tlb->prot & PAGE_EXEC) {
2354 ret |= PPC4XX_TLBLO_EX;
2356 if (tlb->prot & PAGE_WRITE) {
2357 ret |= PPC4XX_TLBLO_WR;
2359 return ret;
2362 void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
2363 target_ulong val)
2365 CPUState *cs = env_cpu(env);
2366 ppcemb_tlb_t *tlb;
2367 target_ulong page, end;
2369 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
2370 val);
2371 entry &= PPC4XX_TLB_ENTRY_MASK;
2372 tlb = &env->tlb.tlbe[entry];
2373 /* Invalidate previous TLB (if it's valid) */
2374 if (tlb->prot & PAGE_VALID) {
2375 end = tlb->EPN + tlb->size;
2376 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end "
2377 TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2378 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2379 tlb_flush_page(cs, page);
2382 tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
2383 & PPC4XX_TLBHI_SIZE_MASK);
2385 * We cannot handle TLB size < TARGET_PAGE_SIZE.
2386 * If this ever occurs, we should implement TARGET_PAGE_BITS_VARY
2388 if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
2389 cpu_abort(cs, "TLB size " TARGET_FMT_lu " < %u "
2390 "are not supported (%d)\n"
2391 "Please implement TARGET_PAGE_BITS_VARY\n",
2392 tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
2394 tlb->EPN = val & ~(tlb->size - 1);
2395 if (val & PPC4XX_TLBHI_V) {
2396 tlb->prot |= PAGE_VALID;
2397 if (val & PPC4XX_TLBHI_E) {
2398 /* XXX: TO BE FIXED */
2399 cpu_abort(cs,
2400 "Little-endian TLB entries are not supported by now\n");
2402 } else {
2403 tlb->prot &= ~PAGE_VALID;
2405 tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2406 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2407 " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2408 (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2409 tlb->prot & PAGE_READ ? 'r' : '-',
2410 tlb->prot & PAGE_WRITE ? 'w' : '-',
2411 tlb->prot & PAGE_EXEC ? 'x' : '-',
2412 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2413 /* Invalidate new TLB (if valid) */
2414 if (tlb->prot & PAGE_VALID) {
2415 end = tlb->EPN + tlb->size;
2416 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end "
2417 TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2418 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2419 tlb_flush_page(cs, page);
2424 void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry,
2425 target_ulong val)
2427 ppcemb_tlb_t *tlb;
2429 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
2430 val);
2431 entry &= PPC4XX_TLB_ENTRY_MASK;
2432 tlb = &env->tlb.tlbe[entry];
2433 tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
2434 tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
2435 tlb->prot = PAGE_READ;
2436 if (val & PPC4XX_TLBLO_EX) {
2437 tlb->prot |= PAGE_EXEC;
2439 if (val & PPC4XX_TLBLO_WR) {
2440 tlb->prot |= PAGE_WRITE;
2442 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2443 " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2444 (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2445 tlb->prot & PAGE_READ ? 'r' : '-',
2446 tlb->prot & PAGE_WRITE ? 'w' : '-',
2447 tlb->prot & PAGE_EXEC ? 'x' : '-',
2448 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2451 target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address)
2453 return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
2456 /* PowerPC 440 TLB management */
2457 void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry,
2458 target_ulong value)
2460 ppcemb_tlb_t *tlb;
2461 target_ulong EPN, RPN, size;
2462 int do_flush_tlbs;
2464 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n",
2465 __func__, word, (int)entry, value);
2466 do_flush_tlbs = 0;
2467 entry &= 0x3F;
2468 tlb = &env->tlb.tlbe[entry];
2469 switch (word) {
2470 default:
2471 /* Just here to please gcc */
2472 case 0:
2473 EPN = value & 0xFFFFFC00;
2474 if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) {
2475 do_flush_tlbs = 1;
2477 tlb->EPN = EPN;
2478 size = booke_tlb_to_page_size((value >> 4) & 0xF);
2479 if ((tlb->prot & PAGE_VALID) && tlb->size < size) {
2480 do_flush_tlbs = 1;
2482 tlb->size = size;
2483 tlb->attr &= ~0x1;
2484 tlb->attr |= (value >> 8) & 1;
2485 if (value & 0x200) {
2486 tlb->prot |= PAGE_VALID;
2487 } else {
2488 if (tlb->prot & PAGE_VALID) {
2489 tlb->prot &= ~PAGE_VALID;
2490 do_flush_tlbs = 1;
2493 tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2494 if (do_flush_tlbs) {
2495 tlb_flush(env_cpu(env));
2497 break;
2498 case 1:
2499 RPN = value & 0xFFFFFC0F;
2500 if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) {
2501 tlb_flush(env_cpu(env));
2503 tlb->RPN = RPN;
2504 break;
2505 case 2:
2506 tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
2507 tlb->prot = tlb->prot & PAGE_VALID;
2508 if (value & 0x1) {
2509 tlb->prot |= PAGE_READ << 4;
2511 if (value & 0x2) {
2512 tlb->prot |= PAGE_WRITE << 4;
2514 if (value & 0x4) {
2515 tlb->prot |= PAGE_EXEC << 4;
2517 if (value & 0x8) {
2518 tlb->prot |= PAGE_READ;
2520 if (value & 0x10) {
2521 tlb->prot |= PAGE_WRITE;
2523 if (value & 0x20) {
2524 tlb->prot |= PAGE_EXEC;
2526 break;
2530 target_ulong helper_440_tlbre(CPUPPCState *env, uint32_t word,
2531 target_ulong entry)
2533 ppcemb_tlb_t *tlb;
2534 target_ulong ret;
2535 int size;
2537 entry &= 0x3F;
2538 tlb = &env->tlb.tlbe[entry];
2539 switch (word) {
2540 default:
2541 /* Just here to please gcc */
2542 case 0:
2543 ret = tlb->EPN;
2544 size = booke_page_size_to_tlb(tlb->size);
2545 if (size < 0 || size > 0xF) {
2546 size = 1;
2548 ret |= size << 4;
2549 if (tlb->attr & 0x1) {
2550 ret |= 0x100;
2552 if (tlb->prot & PAGE_VALID) {
2553 ret |= 0x200;
2555 env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2556 env->spr[SPR_440_MMUCR] |= tlb->PID;
2557 break;
2558 case 1:
2559 ret = tlb->RPN;
2560 break;
2561 case 2:
2562 ret = tlb->attr & ~0x1;
2563 if (tlb->prot & (PAGE_READ << 4)) {
2564 ret |= 0x1;
2566 if (tlb->prot & (PAGE_WRITE << 4)) {
2567 ret |= 0x2;
2569 if (tlb->prot & (PAGE_EXEC << 4)) {
2570 ret |= 0x4;
2572 if (tlb->prot & PAGE_READ) {
2573 ret |= 0x8;
2575 if (tlb->prot & PAGE_WRITE) {
2576 ret |= 0x10;
2578 if (tlb->prot & PAGE_EXEC) {
2579 ret |= 0x20;
2581 break;
2583 return ret;
2586 target_ulong helper_440_tlbsx(CPUPPCState *env, target_ulong address)
2588 return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
2591 /* PowerPC BookE 2.06 TLB management */
2593 static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env)
2595 uint32_t tlbncfg = 0;
2596 int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
2597 int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
2598 int tlb;
2600 tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2601 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
2603 if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
2604 cpu_abort(env_cpu(env), "we don't support HES yet\n");
2607 return booke206_get_tlbm(env, tlb, ea, esel);
2610 void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid)
2612 env->spr[pidn] = pid;
2613 /* changing PIDs mean we're in a different address space now */
2614 tlb_flush(env_cpu(env));
2617 void helper_booke_set_eplc(CPUPPCState *env, target_ulong val)
2619 env->spr[SPR_BOOKE_EPLC] = val & EPID_MASK;
2620 tlb_flush_by_mmuidx(env_cpu(env), 1 << PPC_TLB_EPID_LOAD);
2622 void helper_booke_set_epsc(CPUPPCState *env, target_ulong val)
2624 env->spr[SPR_BOOKE_EPSC] = val & EPID_MASK;
2625 tlb_flush_by_mmuidx(env_cpu(env), 1 << PPC_TLB_EPID_STORE);
2628 static inline void flush_page(CPUPPCState *env, ppcmas_tlb_t *tlb)
2630 if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
2631 tlb_flush_page(env_cpu(env), tlb->mas2 & MAS2_EPN_MASK);
2632 } else {
2633 tlb_flush(env_cpu(env));
2637 void helper_booke206_tlbwe(CPUPPCState *env)
2639 uint32_t tlbncfg, tlbn;
2640 ppcmas_tlb_t *tlb;
2641 uint32_t size_tlb, size_ps;
2642 target_ulong mask;
2645 switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
2646 case MAS0_WQ_ALWAYS:
2647 /* good to go, write that entry */
2648 break;
2649 case MAS0_WQ_COND:
2650 /* XXX check if reserved */
2651 if (0) {
2652 return;
2654 break;
2655 case MAS0_WQ_CLR_RSRV:
2656 /* XXX clear entry */
2657 return;
2658 default:
2659 /* no idea what to do */
2660 return;
2663 if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
2664 !msr_gs) {
2665 /* XXX we don't support direct LRAT setting yet */
2666 fprintf(stderr, "cpu: don't support LRAT setting yet\n");
2667 return;
2670 tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2671 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
2673 tlb = booke206_cur_tlb(env);
2675 if (!tlb) {
2676 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2677 POWERPC_EXCP_INVAL |
2678 POWERPC_EXCP_INVAL_INVAL, GETPC());
2681 /* check that we support the targeted size */
2682 size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
2683 size_ps = booke206_tlbnps(env, tlbn);
2684 if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
2685 !(size_ps & (1 << size_tlb))) {
2686 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2687 POWERPC_EXCP_INVAL |
2688 POWERPC_EXCP_INVAL_INVAL, GETPC());
2691 if (msr_gs) {
2692 cpu_abort(env_cpu(env), "missing HV implementation\n");
2695 if (tlb->mas1 & MAS1_VALID) {
2697 * Invalidate the page in QEMU TLB if it was a valid entry.
2699 * In "PowerPC e500 Core Family Reference Manual, Rev. 1",
2700 * Section "12.4.2 TLB Write Entry (tlbwe) Instruction":
2701 * (https://www.nxp.com/docs/en/reference-manual/E500CORERM.pdf)
2703 * "Note that when an L2 TLB entry is written, it may be displacing an
2704 * already valid entry in the same L2 TLB location (a victim). If a
2705 * valid L1 TLB entry corresponds to the L2 MMU victim entry, that L1
2706 * TLB entry is automatically invalidated."
2708 flush_page(env, tlb);
2711 tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
2712 env->spr[SPR_BOOKE_MAS3];
2713 tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
2715 if ((env->spr[SPR_MMUCFG] & MMUCFG_MAVN) == MMUCFG_MAVN_V2) {
2716 /* For TLB which has a fixed size TSIZE is ignored with MAV2 */
2717 booke206_fixed_size_tlbn(env, tlbn, tlb);
2718 } else {
2719 if (!(tlbncfg & TLBnCFG_AVAIL)) {
2720 /* force !AVAIL TLB entries to correct page size */
2721 tlb->mas1 &= ~MAS1_TSIZE_MASK;
2722 /* XXX can be configured in MMUCSR0 */
2723 tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
2727 /* Make a mask from TLB size to discard invalid bits in EPN field */
2728 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2729 /* Add a mask for page attributes */
2730 mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E;
2732 if (!msr_cm) {
2734 * Executing a tlbwe instruction in 32-bit mode will set bits
2735 * 0:31 of the TLB EPN field to zero.
2737 mask &= 0xffffffff;
2740 tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask;
2742 if (!(tlbncfg & TLBnCFG_IPROT)) {
2743 /* no IPROT supported by TLB */
2744 tlb->mas1 &= ~MAS1_IPROT;
2747 flush_page(env, tlb);
2750 static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb)
2752 int tlbn = booke206_tlbm_to_tlbn(env, tlb);
2753 int way = booke206_tlbm_to_way(env, tlb);
2755 env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
2756 env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
2757 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2759 env->spr[SPR_BOOKE_MAS1] = tlb->mas1;
2760 env->spr[SPR_BOOKE_MAS2] = tlb->mas2;
2761 env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3;
2762 env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32;
2765 void helper_booke206_tlbre(CPUPPCState *env)
2767 ppcmas_tlb_t *tlb = NULL;
2769 tlb = booke206_cur_tlb(env);
2770 if (!tlb) {
2771 env->spr[SPR_BOOKE_MAS1] = 0;
2772 } else {
2773 booke206_tlb_to_mas(env, tlb);
2777 void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address)
2779 ppcmas_tlb_t *tlb = NULL;
2780 int i, j;
2781 hwaddr raddr;
2782 uint32_t spid, sas;
2784 spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
2785 sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
2787 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2788 int ways = booke206_tlb_ways(env, i);
2790 for (j = 0; j < ways; j++) {
2791 tlb = booke206_get_tlbm(env, i, address, j);
2793 if (!tlb) {
2794 continue;
2797 if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
2798 continue;
2801 if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
2802 continue;
2805 booke206_tlb_to_mas(env, tlb);
2806 return;
2810 /* no entry found, fill with defaults */
2811 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
2812 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
2813 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
2814 env->spr[SPR_BOOKE_MAS3] = 0;
2815 env->spr[SPR_BOOKE_MAS7] = 0;
2817 if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
2818 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
2821 env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
2822 << MAS1_TID_SHIFT;
2824 /* next victim logic */
2825 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
2826 env->last_way++;
2827 env->last_way &= booke206_tlb_ways(env, 0) - 1;
2828 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2831 static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
2832 uint32_t ea)
2834 int i;
2835 int ways = booke206_tlb_ways(env, tlbn);
2836 target_ulong mask;
2838 for (i = 0; i < ways; i++) {
2839 ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
2840 if (!tlb) {
2841 continue;
2843 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2844 if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
2845 !(tlb->mas1 & MAS1_IPROT)) {
2846 tlb->mas1 &= ~MAS1_VALID;
2851 void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
2853 CPUState *cs;
2855 if (address & 0x4) {
2856 /* flush all entries */
2857 if (address & 0x8) {
2858 /* flush all of TLB1 */
2859 booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
2860 } else {
2861 /* flush all of TLB0 */
2862 booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
2864 return;
2867 if (address & 0x8) {
2868 /* flush TLB1 entries */
2869 booke206_invalidate_ea_tlb(env, 1, address);
2870 CPU_FOREACH(cs) {
2871 tlb_flush(cs);
2873 } else {
2874 /* flush TLB0 entries */
2875 booke206_invalidate_ea_tlb(env, 0, address);
2876 CPU_FOREACH(cs) {
2877 tlb_flush_page(cs, address & MAS2_EPN_MASK);
2882 void helper_booke206_tlbilx0(CPUPPCState *env, target_ulong address)
2884 /* XXX missing LPID handling */
2885 booke206_flush_tlb(env, -1, 1);
2888 void helper_booke206_tlbilx1(CPUPPCState *env, target_ulong address)
2890 int i, j;
2891 int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2892 ppcmas_tlb_t *tlb = env->tlb.tlbm;
2893 int tlb_size;
2895 /* XXX missing LPID handling */
2896 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2897 tlb_size = booke206_tlb_size(env, i);
2898 for (j = 0; j < tlb_size; j++) {
2899 if (!(tlb[j].mas1 & MAS1_IPROT) &&
2900 ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
2901 tlb[j].mas1 &= ~MAS1_VALID;
2904 tlb += booke206_tlb_size(env, i);
2906 tlb_flush(env_cpu(env));
2909 void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address)
2911 int i, j;
2912 ppcmas_tlb_t *tlb;
2913 int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2914 int pid = tid >> MAS6_SPID_SHIFT;
2915 int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
2916 int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
2917 /* XXX check for unsupported isize and raise an invalid opcode then */
2918 int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
2919 /* XXX implement MAV2 handling */
2920 bool mav2 = false;
2922 /* XXX missing LPID handling */
2923 /* flush by pid and ea */
2924 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2925 int ways = booke206_tlb_ways(env, i);
2927 for (j = 0; j < ways; j++) {
2928 tlb = booke206_get_tlbm(env, i, address, j);
2929 if (!tlb) {
2930 continue;
2932 if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
2933 (tlb->mas1 & MAS1_IPROT) ||
2934 ((tlb->mas1 & MAS1_IND) != ind) ||
2935 ((tlb->mas8 & MAS8_TGS) != sgs)) {
2936 continue;
2938 if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
2939 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2940 continue;
2942 /* XXX e500mc doesn't match SAS, but other cores might */
2943 tlb->mas1 &= ~MAS1_VALID;
2946 tlb_flush(env_cpu(env));
2949 void helper_booke206_tlbflush(CPUPPCState *env, target_ulong type)
2951 int flags = 0;
2953 if (type & 2) {
2954 flags |= BOOKE206_FLUSH_TLB1;
2957 if (type & 4) {
2958 flags |= BOOKE206_FLUSH_TLB0;
2961 booke206_flush_tlb(env, flags, 1);
2965 void helper_check_tlb_flush_local(CPUPPCState *env)
2967 check_tlb_flush(env, false);
2970 void helper_check_tlb_flush_global(CPUPPCState *env)
2972 check_tlb_flush(env, true);
2975 /*****************************************************************************/
2977 bool ppc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
2978 MMUAccessType access_type, int mmu_idx,
2979 bool probe, uintptr_t retaddr)
2981 PowerPCCPU *cpu = POWERPC_CPU(cs);
2982 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
2983 CPUPPCState *env = &cpu->env;
2984 int ret;
2986 if (pcc->handle_mmu_fault) {
2987 ret = pcc->handle_mmu_fault(cpu, addr, access_type, mmu_idx);
2988 } else {
2989 ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx);
2991 if (unlikely(ret != 0)) {
2992 if (probe) {
2993 return false;
2995 raise_exception_err_ra(env, cs->exception_index, env->error_code,
2996 retaddr);
2998 return true;