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 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/>.
19 #include "qemu/osdep.h"
20 #include "qapi/error.h"
22 #include "exec/helper-proto.h"
23 #include "sysemu/kvm.h"
25 #include "mmu-hash64.h"
26 #include "mmu-hash32.h"
27 #include "exec/exec-all.h"
28 #include "exec/cpu_ldst.h"
30 #include "helper_regs.h"
31 #include "qemu/error-report.h"
35 //#define DEBUG_SOFTWARE_TLB
36 //#define DUMP_PAGE_TABLES
37 //#define FLUSH_ALL_TLBS
40 # define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0)
42 # define LOG_MMU_STATE(cpu) do { } while (0)
45 #ifdef DEBUG_SOFTWARE_TLB
46 # define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
48 # define LOG_SWTLB(...) do { } while (0)
52 # define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
54 # define LOG_BATS(...) do { } while (0)
57 /*****************************************************************************/
58 /* PowerPC MMU emulation */
60 /* Context used internally during MMU translations */
61 typedef struct mmu_ctx_t mmu_ctx_t
;
63 hwaddr raddr
; /* Real address */
64 hwaddr eaddr
; /* Effective address */
65 int prot
; /* Protection bits */
66 hwaddr hash
[2]; /* Pagetable hash values */
67 target_ulong ptem
; /* Virtual segment ID | API */
68 int key
; /* Access key */
69 int nx
; /* Non-execute area */
72 /* Common routines used by software and hardware TLBs emulation */
73 static inline int pte_is_valid(target_ulong pte0
)
75 return pte0
& 0x80000000 ? 1 : 0;
78 static inline void pte_invalidate(target_ulong
*pte0
)
83 #define PTE_PTEM_MASK 0x7FFFFFBF
84 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
86 static int pp_check(int key
, int pp
, int nx
)
90 /* Compute access rights */
113 access
= PAGE_READ
| PAGE_WRITE
;
124 static int check_prot(int prot
, int rw
, int access_type
)
128 if (access_type
== ACCESS_CODE
) {
129 if (prot
& PAGE_EXEC
) {
135 if (prot
& PAGE_WRITE
) {
141 if (prot
& PAGE_READ
) {
151 static inline int ppc6xx_tlb_pte_check(mmu_ctx_t
*ctx
, target_ulong pte0
,
152 target_ulong pte1
, int h
, int rw
, int type
)
154 target_ulong ptem
, mmask
;
155 int access
, ret
, pteh
, ptev
, pp
;
158 /* Check validity and table match */
159 ptev
= pte_is_valid(pte0
);
160 pteh
= (pte0
>> 6) & 1;
161 if (ptev
&& h
== pteh
) {
162 /* Check vsid & api */
163 ptem
= pte0
& PTE_PTEM_MASK
;
164 mmask
= PTE_CHECK_MASK
;
165 pp
= pte1
& 0x00000003;
166 if (ptem
== ctx
->ptem
) {
167 if (ctx
->raddr
!= (hwaddr
)-1ULL) {
168 /* all matches should have equal RPN, WIMG & PP */
169 if ((ctx
->raddr
& mmask
) != (pte1
& mmask
)) {
170 qemu_log_mask(CPU_LOG_MMU
, "Bad RPN/WIMG/PP\n");
174 /* Compute access rights */
175 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
176 /* Keep the matching PTE informations */
179 ret
= check_prot(ctx
->prot
, rw
, type
);
182 qemu_log_mask(CPU_LOG_MMU
, "PTE access granted !\n");
184 /* Access right violation */
185 qemu_log_mask(CPU_LOG_MMU
, "PTE access rejected\n");
193 static int pte_update_flags(mmu_ctx_t
*ctx
, target_ulong
*pte1p
,
198 /* Update page flags */
199 if (!(*pte1p
& 0x00000100)) {
200 /* Update accessed flag */
201 *pte1p
|= 0x00000100;
204 if (!(*pte1p
& 0x00000080)) {
205 if (rw
== 1 && ret
== 0) {
206 /* Update changed flag */
207 *pte1p
|= 0x00000080;
210 /* Force page fault for first write access */
211 ctx
->prot
&= ~PAGE_WRITE
;
218 /* Software driven TLB helpers */
219 static inline int ppc6xx_tlb_getnum(CPUPPCState
*env
, target_ulong eaddr
,
220 int way
, int is_code
)
224 /* Select TLB num in a way from address */
225 nr
= (eaddr
>> TARGET_PAGE_BITS
) & (env
->tlb_per_way
- 1);
227 nr
+= env
->tlb_per_way
* way
;
228 /* 6xx have separate TLBs for instructions and data */
229 if (is_code
&& env
->id_tlbs
== 1) {
236 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState
*env
)
238 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
242 /* LOG_SWTLB("Invalidate all TLBs\n"); */
243 /* Invalidate all defined software TLB */
245 if (env
->id_tlbs
== 1) {
248 for (nr
= 0; nr
< max
; nr
++) {
249 tlb
= &env
->tlb
.tlb6
[nr
];
250 pte_invalidate(&tlb
->pte0
);
255 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState
*env
,
257 int is_code
, int match_epn
)
259 #if !defined(FLUSH_ALL_TLBS)
260 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
264 /* Invalidate ITLB + DTLB, all ways */
265 for (way
= 0; way
< env
->nb_ways
; way
++) {
266 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
, is_code
);
267 tlb
= &env
->tlb
.tlb6
[nr
];
268 if (pte_is_valid(tlb
->pte0
) && (match_epn
== 0 || eaddr
== tlb
->EPN
)) {
269 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx
"\n", nr
,
271 pte_invalidate(&tlb
->pte0
);
272 tlb_flush_page(cs
, tlb
->EPN
);
276 /* XXX: PowerPC specification say this is valid as well */
277 ppc6xx_tlb_invalidate_all(env
);
281 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState
*env
,
282 target_ulong eaddr
, int is_code
)
284 ppc6xx_tlb_invalidate_virt2(env
, eaddr
, is_code
, 0);
287 static void ppc6xx_tlb_store(CPUPPCState
*env
, target_ulong EPN
, int way
,
288 int is_code
, target_ulong pte0
, target_ulong pte1
)
293 nr
= ppc6xx_tlb_getnum(env
, EPN
, way
, is_code
);
294 tlb
= &env
->tlb
.tlb6
[nr
];
295 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
296 " PTE1 " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
, EPN
, pte0
, pte1
);
297 /* Invalidate any pending reference in QEMU for this virtual address */
298 ppc6xx_tlb_invalidate_virt2(env
, EPN
, is_code
, 1);
302 /* Store last way for LRU mechanism */
306 static inline int ppc6xx_tlb_check(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
307 target_ulong eaddr
, int rw
, int access_type
)
314 ret
= -1; /* No TLB found */
315 for (way
= 0; way
< env
->nb_ways
; way
++) {
316 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
,
317 access_type
== ACCESS_CODE
? 1 : 0);
318 tlb
= &env
->tlb
.tlb6
[nr
];
319 /* This test "emulates" the PTE index match for hardware TLBs */
320 if ((eaddr
& TARGET_PAGE_MASK
) != tlb
->EPN
) {
321 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx
" " TARGET_FMT_lx
322 "] <> " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
,
323 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
324 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
, eaddr
);
327 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx
" <> " TARGET_FMT_lx
" "
328 TARGET_FMT_lx
" %c %c\n", nr
, env
->nb_tlb
,
329 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
330 tlb
->EPN
, eaddr
, tlb
->pte1
,
331 rw
? 'S' : 'L', access_type
== ACCESS_CODE
? 'I' : 'D');
332 switch (ppc6xx_tlb_pte_check(ctx
, tlb
->pte0
, tlb
->pte1
, 0, rw
, access_type
)) {
334 /* TLB inconsistency */
337 /* Access violation */
347 /* XXX: we should go on looping to check all TLBs consistency
348 * but we can speed-up the whole thing as the
349 * result would be undefined if TLBs are not consistent.
358 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx
" prot=%01x ret=%d\n",
359 ctx
->raddr
& TARGET_PAGE_MASK
, ctx
->prot
, ret
);
360 /* Update page flags */
361 pte_update_flags(ctx
, &env
->tlb
.tlb6
[best
].pte1
, ret
, rw
);
367 /* Perform BAT hit & translation */
368 static inline void bat_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
369 int *validp
, int *protp
, target_ulong
*BATu
,
375 bl
= (*BATu
& 0x00001FFC) << 15;
378 if (((msr_pr
== 0) && (*BATu
& 0x00000002)) ||
379 ((msr_pr
!= 0) && (*BATu
& 0x00000001))) {
381 pp
= *BATl
& 0x00000003;
383 prot
= PAGE_READ
| PAGE_EXEC
;
394 static int get_bat_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
395 target_ulong
virtual, int rw
, int type
)
397 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
398 target_ulong BEPIl
, BEPIu
, bl
;
402 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx
"\n", __func__
,
403 type
== ACCESS_CODE
? 'I' : 'D', virtual);
406 BATlt
= env
->IBAT
[1];
407 BATut
= env
->IBAT
[0];
410 BATlt
= env
->DBAT
[1];
411 BATut
= env
->DBAT
[0];
414 for (i
= 0; i
< env
->nb_BATs
; i
++) {
417 BEPIu
= *BATu
& 0xF0000000;
418 BEPIl
= *BATu
& 0x0FFE0000;
419 bat_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
420 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
421 " BATl " TARGET_FMT_lx
"\n", __func__
,
422 type
== ACCESS_CODE
? 'I' : 'D', i
, virtual, *BATu
, *BATl
);
423 if ((virtual & 0xF0000000) == BEPIu
&&
424 ((virtual & 0x0FFE0000) & ~bl
) == BEPIl
) {
427 /* Get physical address */
428 ctx
->raddr
= (*BATl
& 0xF0000000) |
429 ((virtual & 0x0FFE0000 & bl
) | (*BATl
& 0x0FFE0000)) |
430 (virtual & 0x0001F000);
431 /* Compute access rights */
433 ret
= check_prot(ctx
->prot
, rw
, type
);
435 LOG_BATS("BAT %d match: r " TARGET_FMT_plx
" prot=%c%c\n",
436 i
, ctx
->raddr
, ctx
->prot
& PAGE_READ
? 'R' : '-',
437 ctx
->prot
& PAGE_WRITE
? 'W' : '-');
444 #if defined(DEBUG_BATS)
445 if (qemu_log_enabled()) {
446 LOG_BATS("no BAT match for " TARGET_FMT_lx
":\n", virtual);
447 for (i
= 0; i
< 4; i
++) {
450 BEPIu
= *BATu
& 0xF0000000;
451 BEPIl
= *BATu
& 0x0FFE0000;
452 bl
= (*BATu
& 0x00001FFC) << 15;
453 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
454 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
455 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
456 __func__
, type
== ACCESS_CODE
? 'I' : 'D', i
, virtual,
457 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
466 /* Perform segment based translation */
467 static inline int get_segment_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
468 target_ulong eaddr
, int rw
, int type
)
470 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
473 int ds
, pr
, target_page_bits
;
475 target_ulong sr
, pgidx
;
480 sr
= env
->sr
[eaddr
>> 28];
481 ctx
->key
= (((sr
& 0x20000000) && (pr
!= 0)) ||
482 ((sr
& 0x40000000) && (pr
== 0))) ? 1 : 0;
483 ds
= sr
& 0x80000000 ? 1 : 0;
484 ctx
->nx
= sr
& 0x10000000 ? 1 : 0;
485 vsid
= sr
& 0x00FFFFFF;
486 target_page_bits
= TARGET_PAGE_BITS
;
487 qemu_log_mask(CPU_LOG_MMU
,
488 "Check segment v=" TARGET_FMT_lx
" %d " TARGET_FMT_lx
489 " nip=" TARGET_FMT_lx
" lr=" TARGET_FMT_lx
490 " ir=%d dr=%d pr=%d %d t=%d\n",
491 eaddr
, (int)(eaddr
>> 28), sr
, env
->nip
, env
->lr
, (int)msr_ir
,
492 (int)msr_dr
, pr
!= 0 ? 1 : 0, rw
, type
);
493 pgidx
= (eaddr
& ~SEGMENT_MASK_256M
) >> target_page_bits
;
495 ctx
->ptem
= (vsid
<< 7) | (pgidx
>> 10);
497 qemu_log_mask(CPU_LOG_MMU
,
498 "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx
"\n",
499 ctx
->key
, ds
, ctx
->nx
, vsid
);
502 /* Check if instruction fetch is allowed, if needed */
503 if (type
!= ACCESS_CODE
|| ctx
->nx
== 0) {
504 /* Page address translation */
505 qemu_log_mask(CPU_LOG_MMU
, "htab_base " TARGET_FMT_plx
506 " htab_mask " TARGET_FMT_plx
507 " hash " TARGET_FMT_plx
"\n",
508 ppc_hash32_hpt_base(cpu
), ppc_hash32_hpt_mask(cpu
), hash
);
510 ctx
->hash
[1] = ~hash
;
512 /* Initialize real address with an invalid value */
513 ctx
->raddr
= (hwaddr
)-1ULL;
514 /* Software TLB search */
515 ret
= ppc6xx_tlb_check(env
, ctx
, eaddr
, rw
, type
);
516 #if defined(DUMP_PAGE_TABLES)
517 if (qemu_loglevel_mask(CPU_LOG_MMU
)) {
518 CPUState
*cs
= ENV_GET_CPU(env
);
520 uint32_t a0
, a1
, a2
, a3
;
522 qemu_log("Page table: " TARGET_FMT_plx
" len " TARGET_FMT_plx
523 "\n", ppc_hash32_hpt_base(cpu
),
524 ppc_hash32_hpt_mask(env
) + 0x80);
525 for (curaddr
= ppc_hash32_hpt_base(cpu
);
526 curaddr
< (ppc_hash32_hpt_base(cpu
)
527 + ppc_hash32_hpt_mask(cpu
) + 0x80);
529 a0
= ldl_phys(cs
->as
, curaddr
);
530 a1
= ldl_phys(cs
->as
, curaddr
+ 4);
531 a2
= ldl_phys(cs
->as
, curaddr
+ 8);
532 a3
= ldl_phys(cs
->as
, curaddr
+ 12);
533 if (a0
!= 0 || a1
!= 0 || a2
!= 0 || a3
!= 0) {
534 qemu_log(TARGET_FMT_plx
": %08x %08x %08x %08x\n",
535 curaddr
, a0
, a1
, a2
, a3
);
541 qemu_log_mask(CPU_LOG_MMU
, "No access allowed\n");
547 qemu_log_mask(CPU_LOG_MMU
, "direct store...\n");
548 /* Direct-store segment : absolutely *BUGGY* for now */
550 /* Direct-store implies a 32-bit MMU.
551 * Check the Segment Register's bus unit ID (BUID).
553 sr
= env
->sr
[eaddr
>> 28];
554 if ((sr
& 0x1FF00000) >> 20 == 0x07f) {
555 /* Memory-forced I/O controller interface access */
556 /* If T=1 and BUID=x'07F', the 601 performs a memory access
557 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
559 ctx
->raddr
= ((sr
& 0xF) << 28) | (eaddr
& 0x0FFFFFFF);
560 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
566 /* Integer load/store : only access allowed */
569 /* No code fetch is allowed in direct-store areas */
572 /* Floating point load/store */
575 /* lwarx, ldarx or srwcx. */
578 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
579 /* Should make the instruction do no-op.
580 * As it already do no-op, it's quite easy :-)
588 qemu_log_mask(CPU_LOG_MMU
, "ERROR: instruction should not need "
589 "address translation\n");
592 if ((rw
== 1 || ctx
->key
!= 1) && (rw
== 0 || ctx
->key
!= 0)) {
603 /* Generic TLB check function for embedded PowerPC implementations */
604 static int ppcemb_tlb_check(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
606 target_ulong address
, uint32_t pid
, int ext
,
611 /* Check valid flag */
612 if (!(tlb
->prot
& PAGE_VALID
)) {
615 mask
= ~(tlb
->size
- 1);
616 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx
" PID %u <=> " TARGET_FMT_lx
617 " " TARGET_FMT_lx
" %u %x\n", __func__
, i
, address
, pid
, tlb
->EPN
,
618 mask
, (uint32_t)tlb
->PID
, tlb
->prot
);
620 if (tlb
->PID
!= 0 && tlb
->PID
!= pid
) {
623 /* Check effective address */
624 if ((address
& mask
) != tlb
->EPN
) {
627 *raddrp
= (tlb
->RPN
& mask
) | (address
& ~mask
);
629 /* Extend the physical address to 36 bits */
630 *raddrp
|= (uint64_t)(tlb
->RPN
& 0xF) << 32;
636 /* Generic TLB search function for PowerPC embedded implementations */
637 static int ppcemb_tlb_search(CPUPPCState
*env
, target_ulong address
,
644 /* Default return value is no match */
646 for (i
= 0; i
< env
->nb_tlb
; i
++) {
647 tlb
= &env
->tlb
.tlbe
[i
];
648 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
, pid
, 0, i
) == 0) {
657 /* Helpers specific to PowerPC 40x implementations */
658 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState
*env
)
660 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
664 for (i
= 0; i
< env
->nb_tlb
; i
++) {
665 tlb
= &env
->tlb
.tlbe
[i
];
666 tlb
->prot
&= ~PAGE_VALID
;
671 static int mmu40x_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
672 target_ulong address
, int rw
,
677 int i
, ret
, zsel
, zpr
, pr
;
680 raddr
= (hwaddr
)-1ULL;
682 for (i
= 0; i
< env
->nb_tlb
; i
++) {
683 tlb
= &env
->tlb
.tlbe
[i
];
684 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
685 env
->spr
[SPR_40x_PID
], 0, i
) < 0) {
688 zsel
= (tlb
->attr
>> 4) & 0xF;
689 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (30 - (2 * zsel
))) & 0x3;
690 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
691 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
692 /* Check execute enable bit */
700 /* All accesses granted */
701 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
706 /* Raise Zone protection fault. */
707 env
->spr
[SPR_40x_ESR
] = 1 << 22;
715 /* Check from TLB entry */
716 ctx
->prot
= tlb
->prot
;
717 ret
= check_prot(ctx
->prot
, rw
, access_type
);
719 env
->spr
[SPR_40x_ESR
] = 0;
725 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
726 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
731 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
732 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
737 void store_40x_sler(CPUPPCState
*env
, uint32_t val
)
739 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
741 /* XXX: TO BE FIXED */
742 if (val
!= 0x00000000) {
743 cpu_abort(CPU(cpu
), "Little-endian regions are not supported by now\n");
745 env
->spr
[SPR_405_SLER
] = val
;
748 static inline int mmubooke_check_tlb(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
749 hwaddr
*raddr
, int *prot
,
750 target_ulong address
, int rw
,
751 int access_type
, int i
)
755 if (ppcemb_tlb_check(env
, tlb
, raddr
, address
,
756 env
->spr
[SPR_BOOKE_PID
],
757 !env
->nb_pids
, i
) >= 0) {
761 if (env
->spr
[SPR_BOOKE_PID1
] &&
762 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
763 env
->spr
[SPR_BOOKE_PID1
], 0, i
) >= 0) {
767 if (env
->spr
[SPR_BOOKE_PID2
] &&
768 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
769 env
->spr
[SPR_BOOKE_PID2
], 0, i
) >= 0) {
773 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
779 prot2
= tlb
->prot
& 0xF;
781 prot2
= (tlb
->prot
>> 4) & 0xF;
784 /* Check the address space */
785 if (access_type
== ACCESS_CODE
) {
786 if (msr_ir
!= (tlb
->attr
& 1)) {
787 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
792 if (prot2
& PAGE_EXEC
) {
793 LOG_SWTLB("%s: good TLB!\n", __func__
);
797 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
800 if (msr_dr
!= (tlb
->attr
& 1)) {
801 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
806 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
807 LOG_SWTLB("%s: found TLB!\n", __func__
);
811 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
818 static int mmubooke_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
819 target_ulong address
, int rw
,
827 raddr
= (hwaddr
)-1ULL;
828 for (i
= 0; i
< env
->nb_tlb
; i
++) {
829 tlb
= &env
->tlb
.tlbe
[i
];
830 ret
= mmubooke_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
, rw
,
839 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
840 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
843 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
844 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
850 static void booke206_flush_tlb(CPUPPCState
*env
, int flags
,
851 const int check_iprot
)
853 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
856 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
858 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
859 if (flags
& (1 << i
)) {
860 tlb_size
= booke206_tlb_size(env
, i
);
861 for (j
= 0; j
< tlb_size
; j
++) {
862 if (!check_iprot
|| !(tlb
[j
].mas1
& MAS1_IPROT
)) {
863 tlb
[j
].mas1
&= ~MAS1_VALID
;
867 tlb
+= booke206_tlb_size(env
, i
);
873 static hwaddr
booke206_tlb_to_page_size(CPUPPCState
*env
,
878 tlbm_size
= (tlb
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
880 return 1024ULL << tlbm_size
;
883 /* TLB check function for MAS based SoftTLBs */
884 static int ppcmas_tlb_check(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
885 hwaddr
*raddrp
, target_ulong address
,
892 /* In 32bit mode we can only address 32bit EAs */
893 address
= (uint32_t)address
;
896 /* Check valid flag */
897 if (!(tlb
->mas1
& MAS1_VALID
)) {
901 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
902 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx
" PID=0x%x MAS1=0x%x MAS2=0x%"
903 PRIx64
" mask=0x%" HWADDR_PRIx
" MAS7_3=0x%" PRIx64
" MAS8=0x%"
904 PRIx32
"\n", __func__
, address
, pid
, tlb
->mas1
, tlb
->mas2
, mask
,
905 tlb
->mas7_3
, tlb
->mas8
);
908 tlb_pid
= (tlb
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
;
909 if (tlb_pid
!= 0 && tlb_pid
!= pid
) {
913 /* Check effective address */
914 if ((address
& mask
) != (tlb
->mas2
& MAS2_EPN_MASK
)) {
919 *raddrp
= (tlb
->mas7_3
& mask
) | (address
& ~mask
);
925 static int mmubooke206_check_tlb(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
926 hwaddr
*raddr
, int *prot
,
927 target_ulong address
, int rw
,
933 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
,
934 env
->spr
[SPR_BOOKE_PID
]) >= 0) {
938 if (env
->spr
[SPR_BOOKE_PID1
] &&
939 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
940 env
->spr
[SPR_BOOKE_PID1
]) >= 0) {
944 if (env
->spr
[SPR_BOOKE_PID2
] &&
945 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
946 env
->spr
[SPR_BOOKE_PID2
]) >= 0) {
950 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
956 if (tlb
->mas7_3
& MAS3_UR
) {
959 if (tlb
->mas7_3
& MAS3_UW
) {
962 if (tlb
->mas7_3
& MAS3_UX
) {
966 if (tlb
->mas7_3
& MAS3_SR
) {
969 if (tlb
->mas7_3
& MAS3_SW
) {
972 if (tlb
->mas7_3
& MAS3_SX
) {
977 /* Check the address space and permissions */
978 if (access_type
== ACCESS_CODE
) {
979 if (msr_ir
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
980 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
985 if (prot2
& PAGE_EXEC
) {
986 LOG_SWTLB("%s: good TLB!\n", __func__
);
990 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
993 if (msr_dr
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
994 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
999 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
1000 LOG_SWTLB("%s: found TLB!\n", __func__
);
1004 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
1011 static int mmubooke206_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1012 target_ulong address
, int rw
,
1020 raddr
= (hwaddr
)-1ULL;
1022 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1023 int ways
= booke206_tlb_ways(env
, i
);
1025 for (j
= 0; j
< ways
; j
++) {
1026 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
1030 ret
= mmubooke206_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
,
1042 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
1043 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1046 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
1047 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
1053 static const char *book3e_tsize_to_str
[32] = {
1054 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1055 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1056 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1060 static void mmubooke_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1063 ppcemb_tlb_t
*entry
;
1066 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1067 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1071 cpu_fprintf(f
, "\nTLB:\n");
1072 cpu_fprintf(f
, "Effective Physical Size PID Prot "
1075 entry
= &env
->tlb
.tlbe
[0];
1076 for (i
= 0; i
< env
->nb_tlb
; i
++, entry
++) {
1079 uint64_t size
= (uint64_t)entry
->size
;
1082 /* Check valid flag */
1083 if (!(entry
->prot
& PAGE_VALID
)) {
1087 mask
= ~(entry
->size
- 1);
1088 ea
= entry
->EPN
& mask
;
1089 pa
= entry
->RPN
& mask
;
1090 /* Extend the physical address to 36 bits */
1091 pa
|= (hwaddr
)(entry
->RPN
& 0xF) << 32;
1094 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"M", size
/ 1024);
1096 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"k", size
);
1098 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %s %-5u %08x %08x\n",
1099 (uint64_t)ea
, (uint64_t)pa
, size_buf
, (uint32_t)entry
->PID
,
1100 entry
->prot
, entry
->attr
);
1105 static void mmubooke206_dump_one_tlb(FILE *f
, fprintf_function cpu_fprintf
,
1106 CPUPPCState
*env
, int tlbn
, int offset
,
1109 ppcmas_tlb_t
*entry
;
1112 cpu_fprintf(f
, "\nTLB%d:\n", tlbn
);
1113 cpu_fprintf(f
, "Effective Physical Size TID TS SRWX"
1114 " URWX WIMGE U0123\n");
1116 entry
= &env
->tlb
.tlbm
[offset
];
1117 for (i
= 0; i
< tlbsize
; i
++, entry
++) {
1118 hwaddr ea
, pa
, size
;
1121 if (!(entry
->mas1
& MAS1_VALID
)) {
1125 tsize
= (entry
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1126 size
= 1024ULL << tsize
;
1127 ea
= entry
->mas2
& ~(size
- 1);
1128 pa
= entry
->mas7_3
& ~(size
- 1);
1130 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %4s %-5u %1u S%c%c%c"
1131 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1132 (uint64_t)ea
, (uint64_t)pa
,
1133 book3e_tsize_to_str
[tsize
],
1134 (entry
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
,
1135 (entry
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
,
1136 entry
->mas7_3
& MAS3_SR
? 'R' : '-',
1137 entry
->mas7_3
& MAS3_SW
? 'W' : '-',
1138 entry
->mas7_3
& MAS3_SX
? 'X' : '-',
1139 entry
->mas7_3
& MAS3_UR
? 'R' : '-',
1140 entry
->mas7_3
& MAS3_UW
? 'W' : '-',
1141 entry
->mas7_3
& MAS3_UX
? 'X' : '-',
1142 entry
->mas2
& MAS2_W
? 'W' : '-',
1143 entry
->mas2
& MAS2_I
? 'I' : '-',
1144 entry
->mas2
& MAS2_M
? 'M' : '-',
1145 entry
->mas2
& MAS2_G
? 'G' : '-',
1146 entry
->mas2
& MAS2_E
? 'E' : '-',
1147 entry
->mas7_3
& MAS3_U0
? '0' : '-',
1148 entry
->mas7_3
& MAS3_U1
? '1' : '-',
1149 entry
->mas7_3
& MAS3_U2
? '2' : '-',
1150 entry
->mas7_3
& MAS3_U3
? '3' : '-');
1154 static void mmubooke206_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1160 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1161 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1165 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1166 int size
= booke206_tlb_size(env
, i
);
1172 mmubooke206_dump_one_tlb(f
, cpu_fprintf
, env
, i
, offset
, size
);
1177 static void mmu6xx_dump_BATs(FILE *f
, fprintf_function cpu_fprintf
,
1178 CPUPPCState
*env
, int type
)
1180 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
1181 target_ulong BEPIl
, BEPIu
, bl
;
1186 BATlt
= env
->IBAT
[1];
1187 BATut
= env
->IBAT
[0];
1190 BATlt
= env
->DBAT
[1];
1191 BATut
= env
->DBAT
[0];
1195 for (i
= 0; i
< env
->nb_BATs
; i
++) {
1198 BEPIu
= *BATu
& 0xF0000000;
1199 BEPIl
= *BATu
& 0x0FFE0000;
1200 bl
= (*BATu
& 0x00001FFC) << 15;
1201 cpu_fprintf(f
, "%s BAT%d BATu " TARGET_FMT_lx
1202 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
1203 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
1204 type
== ACCESS_CODE
? "code" : "data", i
,
1205 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
1209 static void mmu6xx_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1212 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1215 int type
, way
, entry
, i
;
1217 cpu_fprintf(f
, "HTAB base = 0x%"HWADDR_PRIx
"\n", ppc_hash32_hpt_base(cpu
));
1218 cpu_fprintf(f
, "HTAB mask = 0x%"HWADDR_PRIx
"\n", ppc_hash32_hpt_mask(cpu
));
1220 cpu_fprintf(f
, "\nSegment registers:\n");
1221 for (i
= 0; i
< 32; i
++) {
1223 if (sr
& 0x80000000) {
1224 cpu_fprintf(f
, "%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1225 "CNTLR_SPEC=0x%05x\n", i
,
1226 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1227 sr
& 0x20000000 ? 1 : 0, (uint32_t)((sr
>> 20) & 0x1FF),
1228 (uint32_t)(sr
& 0xFFFFF));
1230 cpu_fprintf(f
, "%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i
,
1231 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1232 sr
& 0x20000000 ? 1 : 0, sr
& 0x10000000 ? 1 : 0,
1233 (uint32_t)(sr
& 0x00FFFFFF));
1237 cpu_fprintf(f
, "\nBATs:\n");
1238 mmu6xx_dump_BATs(f
, cpu_fprintf
, env
, ACCESS_INT
);
1239 mmu6xx_dump_BATs(f
, cpu_fprintf
, env
, ACCESS_CODE
);
1241 if (env
->id_tlbs
!= 1) {
1242 cpu_fprintf(f
, "ERROR: 6xx MMU should have separated TLB"
1243 " for code and data\n");
1246 cpu_fprintf(f
, "\nTLBs [EPN EPN + SIZE]\n");
1248 for (type
= 0; type
< 2; type
++) {
1249 for (way
= 0; way
< env
->nb_ways
; way
++) {
1250 for (entry
= env
->nb_tlb
* type
+ env
->tlb_per_way
* way
;
1251 entry
< (env
->nb_tlb
* type
+ env
->tlb_per_way
* (way
+ 1));
1254 tlb
= &env
->tlb
.tlb6
[entry
];
1255 cpu_fprintf(f
, "%s TLB %02d/%02d way:%d %s ["
1256 TARGET_FMT_lx
" " TARGET_FMT_lx
"]\n",
1257 type
? "code" : "data", entry
% env
->nb_tlb
,
1259 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
1260 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
);
1266 void dump_mmu(FILE *f
, fprintf_function cpu_fprintf
, CPUPPCState
*env
)
1268 switch (env
->mmu_model
) {
1269 case POWERPC_MMU_BOOKE
:
1270 mmubooke_dump_mmu(f
, cpu_fprintf
, env
);
1272 case POWERPC_MMU_BOOKE206
:
1273 mmubooke206_dump_mmu(f
, cpu_fprintf
, env
);
1275 case POWERPC_MMU_SOFT_6xx
:
1276 case POWERPC_MMU_SOFT_74xx
:
1277 mmu6xx_dump_mmu(f
, cpu_fprintf
, env
);
1279 #if defined(TARGET_PPC64)
1280 case POWERPC_MMU_64B
:
1281 case POWERPC_MMU_2_03
:
1282 case POWERPC_MMU_2_06
:
1283 case POWERPC_MMU_2_06a
:
1284 case POWERPC_MMU_2_07
:
1285 case POWERPC_MMU_2_07a
:
1286 dump_slb(f
, cpu_fprintf
, ppc_env_get_cpu(env
));
1290 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented\n", __func__
);
1294 static inline int check_physical(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1295 target_ulong eaddr
, int rw
)
1300 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1302 switch (env
->mmu_model
) {
1303 case POWERPC_MMU_SOFT_6xx
:
1304 case POWERPC_MMU_SOFT_74xx
:
1305 case POWERPC_MMU_SOFT_4xx
:
1306 case POWERPC_MMU_REAL
:
1307 case POWERPC_MMU_BOOKE
:
1308 ctx
->prot
|= PAGE_WRITE
;
1311 case POWERPC_MMU_SOFT_4xx_Z
:
1312 if (unlikely(msr_pe
!= 0)) {
1313 /* 403 family add some particular protections,
1314 * using PBL/PBU registers for accesses with no translation.
1317 /* Check PLB validity */
1318 (env
->pb
[0] < env
->pb
[1] &&
1319 /* and address in plb area */
1320 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1321 (env
->pb
[2] < env
->pb
[3] &&
1322 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1323 if (in_plb
^ msr_px
) {
1324 /* Access in protected area */
1326 /* Access is not allowed */
1330 /* Read-write access is allowed */
1331 ctx
->prot
|= PAGE_WRITE
;
1337 /* Caller's checks mean we should never get here for other models */
1345 static int get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1346 target_ulong eaddr
, int rw
, int access_type
)
1348 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1350 bool real_mode
= (access_type
== ACCESS_CODE
&& msr_ir
== 0)
1351 || (access_type
!= ACCESS_CODE
&& msr_dr
== 0);
1354 qemu_log("%s\n", __func__
);
1357 switch (env
->mmu_model
) {
1358 case POWERPC_MMU_SOFT_6xx
:
1359 case POWERPC_MMU_SOFT_74xx
:
1361 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1363 /* Try to find a BAT */
1364 if (env
->nb_BATs
!= 0) {
1365 ret
= get_bat_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1368 /* We didn't match any BAT entry or don't have BATs */
1369 ret
= get_segment_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1374 case POWERPC_MMU_SOFT_4xx
:
1375 case POWERPC_MMU_SOFT_4xx_Z
:
1377 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1379 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1383 case POWERPC_MMU_BOOKE
:
1384 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1387 case POWERPC_MMU_BOOKE206
:
1388 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1391 case POWERPC_MMU_MPC8xx
:
1393 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1395 case POWERPC_MMU_REAL
:
1397 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1399 cpu_abort(CPU(cpu
), "PowerPC in real mode do not do any translation\n");
1403 cpu_abort(CPU(cpu
), "Unknown or invalid MMU model\n");
1407 qemu_log("%s address " TARGET_FMT_lx
" => %d " TARGET_FMT_plx
"\n",
1408 __func__
, eaddr
, ret
, ctx
->raddr
);
1414 hwaddr
ppc_cpu_get_phys_page_debug(CPUState
*cs
, vaddr addr
)
1416 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
1417 CPUPPCState
*env
= &cpu
->env
;
1420 switch (env
->mmu_model
) {
1421 #if defined(TARGET_PPC64)
1422 case POWERPC_MMU_64B
:
1423 case POWERPC_MMU_2_03
:
1424 case POWERPC_MMU_2_06
:
1425 case POWERPC_MMU_2_06a
:
1426 case POWERPC_MMU_2_07
:
1427 case POWERPC_MMU_2_07a
:
1428 return ppc_hash64_get_phys_page_debug(cpu
, addr
);
1431 case POWERPC_MMU_32B
:
1432 case POWERPC_MMU_601
:
1433 return ppc_hash32_get_phys_page_debug(cpu
, addr
);
1439 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0)) {
1441 /* Some MMUs have separate TLBs for code and data. If we only try an
1442 * ACCESS_INT, we may not be able to read instructions mapped by code
1443 * TLBs, so we also try a ACCESS_CODE.
1445 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0,
1446 ACCESS_CODE
) != 0)) {
1451 return ctx
.raddr
& TARGET_PAGE_MASK
;
1454 static void booke206_update_mas_tlb_miss(CPUPPCState
*env
, target_ulong address
,
1457 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
1458 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
1459 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
1460 env
->spr
[SPR_BOOKE_MAS3
] = 0;
1461 env
->spr
[SPR_BOOKE_MAS6
] = 0;
1462 env
->spr
[SPR_BOOKE_MAS7
] = 0;
1465 if (((rw
== 2) && msr_ir
) || ((rw
!= 2) && msr_dr
)) {
1466 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
1467 env
->spr
[SPR_BOOKE_MAS6
] |= MAS6_SAS
;
1470 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_VALID
;
1471 env
->spr
[SPR_BOOKE_MAS2
] |= address
& MAS2_EPN_MASK
;
1473 switch (env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TIDSELD_PIDZ
) {
1474 case MAS4_TIDSELD_PID0
:
1475 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID
] << MAS1_TID_SHIFT
;
1477 case MAS4_TIDSELD_PID1
:
1478 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID1
] << MAS1_TID_SHIFT
;
1480 case MAS4_TIDSELD_PID2
:
1481 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID2
] << MAS1_TID_SHIFT
;
1485 env
->spr
[SPR_BOOKE_MAS6
] |= env
->spr
[SPR_BOOKE_PID
] << 16;
1487 /* next victim logic */
1488 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
1490 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
1491 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
1494 /* Perform address translation */
1495 static int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
,
1496 int rw
, int mmu_idx
)
1498 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1499 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
1507 access_type
= ACCESS_CODE
;
1510 access_type
= env
->access_type
;
1512 ret
= get_physical_address(env
, &ctx
, address
, rw
, access_type
);
1514 tlb_set_page(cs
, address
& TARGET_PAGE_MASK
,
1515 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1516 mmu_idx
, TARGET_PAGE_SIZE
);
1518 } else if (ret
< 0) {
1520 if (access_type
== ACCESS_CODE
) {
1523 /* No matches in page tables or TLB */
1524 switch (env
->mmu_model
) {
1525 case POWERPC_MMU_SOFT_6xx
:
1526 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1527 env
->error_code
= 1 << 18;
1528 env
->spr
[SPR_IMISS
] = address
;
1529 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1531 case POWERPC_MMU_SOFT_74xx
:
1532 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1534 case POWERPC_MMU_SOFT_4xx
:
1535 case POWERPC_MMU_SOFT_4xx_Z
:
1536 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1537 env
->error_code
= 0;
1538 env
->spr
[SPR_40x_DEAR
] = address
;
1539 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1541 case POWERPC_MMU_BOOKE206
:
1542 booke206_update_mas_tlb_miss(env
, address
, rw
);
1544 case POWERPC_MMU_BOOKE
:
1545 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1546 env
->error_code
= 0;
1547 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1549 case POWERPC_MMU_MPC8xx
:
1551 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1553 case POWERPC_MMU_REAL
:
1554 cpu_abort(cs
, "PowerPC in real mode should never raise "
1555 "any MMU exceptions\n");
1558 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1563 /* Access rights violation */
1564 cs
->exception_index
= POWERPC_EXCP_ISI
;
1565 env
->error_code
= 0x08000000;
1568 /* No execute protection violation */
1569 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1570 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1571 env
->spr
[SPR_BOOKE_ESR
] = 0x00000000;
1573 cs
->exception_index
= POWERPC_EXCP_ISI
;
1574 env
->error_code
= 0x10000000;
1577 /* Direct store exception */
1578 /* No code fetch is allowed in direct-store areas */
1579 cs
->exception_index
= POWERPC_EXCP_ISI
;
1580 env
->error_code
= 0x10000000;
1586 /* No matches in page tables or TLB */
1587 switch (env
->mmu_model
) {
1588 case POWERPC_MMU_SOFT_6xx
:
1590 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1591 env
->error_code
= 1 << 16;
1593 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1594 env
->error_code
= 0;
1596 env
->spr
[SPR_DMISS
] = address
;
1597 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1599 env
->error_code
|= ctx
.key
<< 19;
1600 env
->spr
[SPR_HASH1
] = ppc_hash32_hpt_base(cpu
) +
1601 get_pteg_offset32(cpu
, ctx
.hash
[0]);
1602 env
->spr
[SPR_HASH2
] = ppc_hash32_hpt_base(cpu
) +
1603 get_pteg_offset32(cpu
, ctx
.hash
[1]);
1605 case POWERPC_MMU_SOFT_74xx
:
1607 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1609 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1612 /* Implement LRU algorithm */
1613 env
->error_code
= ctx
.key
<< 19;
1614 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1615 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1616 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1618 case POWERPC_MMU_SOFT_4xx
:
1619 case POWERPC_MMU_SOFT_4xx_Z
:
1620 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1621 env
->error_code
= 0;
1622 env
->spr
[SPR_40x_DEAR
] = address
;
1624 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1626 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1629 case POWERPC_MMU_MPC8xx
:
1631 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1633 case POWERPC_MMU_BOOKE206
:
1634 booke206_update_mas_tlb_miss(env
, address
, rw
);
1636 case POWERPC_MMU_BOOKE
:
1637 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1638 env
->error_code
= 0;
1639 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1640 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1642 case POWERPC_MMU_REAL
:
1643 cpu_abort(cs
, "PowerPC in real mode should never raise "
1644 "any MMU exceptions\n");
1647 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1652 /* Access rights violation */
1653 cs
->exception_index
= POWERPC_EXCP_DSI
;
1654 env
->error_code
= 0;
1655 if (env
->mmu_model
== POWERPC_MMU_SOFT_4xx
1656 || env
->mmu_model
== POWERPC_MMU_SOFT_4xx_Z
) {
1657 env
->spr
[SPR_40x_DEAR
] = address
;
1659 env
->spr
[SPR_40x_ESR
] |= 0x00800000;
1661 } else if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1662 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1663 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1664 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1666 env
->spr
[SPR_DAR
] = address
;
1668 env
->spr
[SPR_DSISR
] = 0x0A000000;
1670 env
->spr
[SPR_DSISR
] = 0x08000000;
1675 /* Direct store exception */
1676 switch (access_type
) {
1678 /* Floating point load/store */
1679 cs
->exception_index
= POWERPC_EXCP_ALIGN
;
1680 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1681 env
->spr
[SPR_DAR
] = address
;
1684 /* lwarx, ldarx or stwcx. */
1685 cs
->exception_index
= POWERPC_EXCP_DSI
;
1686 env
->error_code
= 0;
1687 env
->spr
[SPR_DAR
] = address
;
1689 env
->spr
[SPR_DSISR
] = 0x06000000;
1691 env
->spr
[SPR_DSISR
] = 0x04000000;
1695 /* eciwx or ecowx */
1696 cs
->exception_index
= POWERPC_EXCP_DSI
;
1697 env
->error_code
= 0;
1698 env
->spr
[SPR_DAR
] = address
;
1700 env
->spr
[SPR_DSISR
] = 0x06100000;
1702 env
->spr
[SPR_DSISR
] = 0x04100000;
1706 printf("DSI: invalid exception (%d)\n", ret
);
1707 cs
->exception_index
= POWERPC_EXCP_PROGRAM
;
1709 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1710 env
->spr
[SPR_DAR
] = address
;
1717 printf("%s: set exception to %d %02x\n", __func__
,
1718 cs
->exception
, env
->error_code
);
1726 /*****************************************************************************/
1727 /* BATs management */
1728 #if !defined(FLUSH_ALL_TLBS)
1729 static inline void do_invalidate_BAT(CPUPPCState
*env
, target_ulong BATu
,
1732 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1733 target_ulong base
, end
, page
;
1735 base
= BATu
& ~0x0001FFFF;
1736 end
= base
+ mask
+ 0x00020000;
1737 LOG_BATS("Flush BAT from " TARGET_FMT_lx
" to " TARGET_FMT_lx
" ("
1738 TARGET_FMT_lx
")\n", base
, end
, mask
);
1739 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
1740 tlb_flush_page(cs
, page
);
1742 LOG_BATS("Flush done\n");
1746 static inline void dump_store_bat(CPUPPCState
*env
, char ID
, int ul
, int nr
,
1749 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx
" (" TARGET_FMT_lx
")\n", ID
,
1750 nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1753 void helper_store_ibatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1756 #if defined(FLUSH_ALL_TLBS)
1757 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1760 dump_store_bat(env
, 'I', 0, nr
, value
);
1761 if (env
->IBAT
[0][nr
] != value
) {
1762 mask
= (value
<< 15) & 0x0FFE0000UL
;
1763 #if !defined(FLUSH_ALL_TLBS)
1764 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1766 /* When storing valid upper BAT, mask BEPI and BRPN
1767 * and invalidate all TLBs covered by this BAT
1769 mask
= (value
<< 15) & 0x0FFE0000UL
;
1770 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1771 (value
& ~0x0001FFFFUL
& ~mask
);
1772 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1773 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1774 #if !defined(FLUSH_ALL_TLBS)
1775 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1777 tlb_flush(CPU(cpu
));
1782 void helper_store_ibatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1784 dump_store_bat(env
, 'I', 1, nr
, value
);
1785 env
->IBAT
[1][nr
] = value
;
1788 void helper_store_dbatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1791 #if defined(FLUSH_ALL_TLBS)
1792 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1795 dump_store_bat(env
, 'D', 0, nr
, value
);
1796 if (env
->DBAT
[0][nr
] != value
) {
1797 /* When storing valid upper BAT, mask BEPI and BRPN
1798 * and invalidate all TLBs covered by this BAT
1800 mask
= (value
<< 15) & 0x0FFE0000UL
;
1801 #if !defined(FLUSH_ALL_TLBS)
1802 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1804 mask
= (value
<< 15) & 0x0FFE0000UL
;
1805 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1806 (value
& ~0x0001FFFFUL
& ~mask
);
1807 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1808 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1809 #if !defined(FLUSH_ALL_TLBS)
1810 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1812 tlb_flush(CPU(cpu
));
1817 void helper_store_dbatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1819 dump_store_bat(env
, 'D', 1, nr
, value
);
1820 env
->DBAT
[1][nr
] = value
;
1823 void helper_store_601_batu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1826 #if defined(FLUSH_ALL_TLBS)
1827 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1831 dump_store_bat(env
, 'I', 0, nr
, value
);
1832 if (env
->IBAT
[0][nr
] != value
) {
1833 #if defined(FLUSH_ALL_TLBS)
1836 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1837 if (env
->IBAT
[1][nr
] & 0x40) {
1838 /* Invalidate BAT only if it is valid */
1839 #if !defined(FLUSH_ALL_TLBS)
1840 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1845 /* When storing valid upper BAT, mask BEPI and BRPN
1846 * and invalidate all TLBs covered by this BAT
1848 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1849 (value
& ~0x0001FFFFUL
& ~mask
);
1850 env
->DBAT
[0][nr
] = env
->IBAT
[0][nr
];
1851 if (env
->IBAT
[1][nr
] & 0x40) {
1852 #if !defined(FLUSH_ALL_TLBS)
1853 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1858 #if defined(FLUSH_ALL_TLBS)
1860 tlb_flush(CPU(cpu
));
1866 void helper_store_601_batl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1868 #if !defined(FLUSH_ALL_TLBS)
1871 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1875 dump_store_bat(env
, 'I', 1, nr
, value
);
1876 if (env
->IBAT
[1][nr
] != value
) {
1877 #if defined(FLUSH_ALL_TLBS)
1880 if (env
->IBAT
[1][nr
] & 0x40) {
1881 #if !defined(FLUSH_ALL_TLBS)
1882 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1883 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1889 #if !defined(FLUSH_ALL_TLBS)
1890 mask
= (value
<< 17) & 0x0FFE0000UL
;
1891 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1896 env
->IBAT
[1][nr
] = value
;
1897 env
->DBAT
[1][nr
] = value
;
1898 #if defined(FLUSH_ALL_TLBS)
1900 tlb_flush(CPU(cpu
));
1906 /*****************************************************************************/
1907 /* TLB management */
1908 void ppc_tlb_invalidate_all(CPUPPCState
*env
)
1910 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1912 switch (env
->mmu_model
) {
1913 case POWERPC_MMU_SOFT_6xx
:
1914 case POWERPC_MMU_SOFT_74xx
:
1915 ppc6xx_tlb_invalidate_all(env
);
1917 case POWERPC_MMU_SOFT_4xx
:
1918 case POWERPC_MMU_SOFT_4xx_Z
:
1919 ppc4xx_tlb_invalidate_all(env
);
1921 case POWERPC_MMU_REAL
:
1922 cpu_abort(CPU(cpu
), "No TLB for PowerPC 4xx in real mode\n");
1924 case POWERPC_MMU_MPC8xx
:
1926 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1928 case POWERPC_MMU_BOOKE
:
1929 tlb_flush(CPU(cpu
));
1931 case POWERPC_MMU_BOOKE206
:
1932 booke206_flush_tlb(env
, -1, 0);
1934 case POWERPC_MMU_32B
:
1935 case POWERPC_MMU_601
:
1936 #if defined(TARGET_PPC64)
1937 case POWERPC_MMU_64B
:
1938 case POWERPC_MMU_2_03
:
1939 case POWERPC_MMU_2_06
:
1940 case POWERPC_MMU_2_06a
:
1941 case POWERPC_MMU_2_07
:
1942 case POWERPC_MMU_2_07a
:
1943 case POWERPC_MMU_3_00
:
1944 #endif /* defined(TARGET_PPC64) */
1945 env
->tlb_need_flush
= 0;
1946 tlb_flush(CPU(cpu
));
1950 cpu_abort(CPU(cpu
), "Unknown MMU model %d\n", env
->mmu_model
);
1955 void ppc_tlb_invalidate_one(CPUPPCState
*env
, target_ulong addr
)
1957 #if !defined(FLUSH_ALL_TLBS)
1958 addr
&= TARGET_PAGE_MASK
;
1959 switch (env
->mmu_model
) {
1960 case POWERPC_MMU_SOFT_6xx
:
1961 case POWERPC_MMU_SOFT_74xx
:
1962 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
1963 if (env
->id_tlbs
== 1) {
1964 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
1967 case POWERPC_MMU_32B
:
1968 case POWERPC_MMU_601
:
1969 /* Actual CPUs invalidate entire congruence classes based on the
1970 * geometry of their TLBs and some OSes take that into account,
1971 * we just mark the TLB to be flushed later (context synchronizing
1972 * event or sync instruction on 32-bit).
1974 env
->tlb_need_flush
|= TLB_NEED_LOCAL_FLUSH
;
1976 #if defined(TARGET_PPC64)
1977 case POWERPC_MMU_64B
:
1978 case POWERPC_MMU_2_03
:
1979 case POWERPC_MMU_2_06
:
1980 case POWERPC_MMU_2_06a
:
1981 case POWERPC_MMU_2_07
:
1982 case POWERPC_MMU_2_07a
:
1983 case POWERPC_MMU_3_00
:
1984 /* tlbie invalidate TLBs for all segments */
1985 /* XXX: given the fact that there are too many segments to invalidate,
1986 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
1987 * we just invalidate all TLBs
1989 env
->tlb_need_flush
|= TLB_NEED_LOCAL_FLUSH
;
1991 #endif /* defined(TARGET_PPC64) */
1993 /* Should never reach here with other MMU models */
1997 ppc_tlb_invalidate_all(env
);
2001 /*****************************************************************************/
2002 /* Special registers manipulation */
2003 void ppc_store_sdr1(CPUPPCState
*env
, target_ulong value
)
2005 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2006 qemu_log_mask(CPU_LOG_MMU
, "%s: " TARGET_FMT_lx
"\n", __func__
, value
);
2008 #if defined(TARGET_PPC64)
2009 if (env
->mmu_model
& POWERPC_MMU_64
) {
2010 target_ulong sdr_mask
= SDR_64_HTABORG
| SDR_64_HTABSIZE
;
2011 target_ulong htabsize
= value
& SDR_64_HTABSIZE
;
2013 if (value
& ~sdr_mask
) {
2014 error_report("Invalid bits 0x"TARGET_FMT_lx
" set in SDR1",
2018 if (htabsize
> 28) {
2019 error_report("Invalid HTABSIZE 0x" TARGET_FMT_lx
" stored in SDR1",
2024 #endif /* defined(TARGET_PPC64) */
2025 /* FIXME: Should check for valid HTABMASK values in 32-bit case */
2026 env
->spr
[SPR_SDR1
] = value
;
2029 /* Segment registers load and store */
2030 target_ulong
helper_load_sr(CPUPPCState
*env
, target_ulong sr_num
)
2032 #if defined(TARGET_PPC64)
2033 if (env
->mmu_model
& POWERPC_MMU_64
) {
2038 return env
->sr
[sr_num
];
2041 void helper_store_sr(CPUPPCState
*env
, target_ulong srnum
, target_ulong value
)
2043 qemu_log_mask(CPU_LOG_MMU
,
2044 "%s: reg=%d " TARGET_FMT_lx
" " TARGET_FMT_lx
"\n", __func__
,
2045 (int)srnum
, value
, env
->sr
[srnum
]);
2046 #if defined(TARGET_PPC64)
2047 if (env
->mmu_model
& POWERPC_MMU_64
) {
2048 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2049 uint64_t esid
, vsid
;
2052 esid
= ((uint64_t)(srnum
& 0xf) << 28) | SLB_ESID_V
;
2055 vsid
= (value
& 0xfffffff) << 12;
2057 vsid
|= ((value
>> 27) & 0xf) << 8;
2059 ppc_store_slb(cpu
, srnum
, esid
, vsid
);
2062 if (env
->sr
[srnum
] != value
) {
2063 env
->sr
[srnum
] = value
;
2064 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2065 flusing the whole TLB. */
2066 #if !defined(FLUSH_ALL_TLBS) && 0
2068 target_ulong page
, end
;
2069 /* Invalidate 256 MB of virtual memory */
2070 page
= (16 << 20) * srnum
;
2071 end
= page
+ (16 << 20);
2072 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
2073 tlb_flush_page(CPU(cpu
), page
);
2077 env
->tlb_need_flush
|= TLB_NEED_LOCAL_FLUSH
;
2082 /* TLB management */
2083 void helper_tlbia(CPUPPCState
*env
)
2085 ppc_tlb_invalidate_all(env
);
2088 void helper_tlbie(CPUPPCState
*env
, target_ulong addr
)
2090 ppc_tlb_invalidate_one(env
, addr
);
2093 void helper_tlbiva(CPUPPCState
*env
, target_ulong addr
)
2095 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2097 /* tlbiva instruction only exists on BookE */
2098 assert(env
->mmu_model
== POWERPC_MMU_BOOKE
);
2100 cpu_abort(CPU(cpu
), "BookE MMU model is not implemented\n");
2103 /* Software driven TLBs management */
2104 /* PowerPC 602/603 software TLB load instructions helpers */
2105 static void do_6xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2107 target_ulong RPN
, CMP
, EPN
;
2110 RPN
= env
->spr
[SPR_RPA
];
2112 CMP
= env
->spr
[SPR_ICMP
];
2113 EPN
= env
->spr
[SPR_IMISS
];
2115 CMP
= env
->spr
[SPR_DCMP
];
2116 EPN
= env
->spr
[SPR_DMISS
];
2118 way
= (env
->spr
[SPR_SRR1
] >> 17) & 1;
2119 (void)EPN
; /* avoid a compiler warning */
2120 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2121 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2123 /* Store this TLB */
2124 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2125 way
, is_code
, CMP
, RPN
);
2128 void helper_6xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2130 do_6xx_tlb(env
, EPN
, 0);
2133 void helper_6xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2135 do_6xx_tlb(env
, EPN
, 1);
2138 /* PowerPC 74xx software TLB load instructions helpers */
2139 static void do_74xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2141 target_ulong RPN
, CMP
, EPN
;
2144 RPN
= env
->spr
[SPR_PTELO
];
2145 CMP
= env
->spr
[SPR_PTEHI
];
2146 EPN
= env
->spr
[SPR_TLBMISS
] & ~0x3;
2147 way
= env
->spr
[SPR_TLBMISS
] & 0x3;
2148 (void)EPN
; /* avoid a compiler warning */
2149 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2150 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2152 /* Store this TLB */
2153 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2154 way
, is_code
, CMP
, RPN
);
2157 void helper_74xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2159 do_74xx_tlb(env
, EPN
, 0);
2162 void helper_74xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2164 do_74xx_tlb(env
, EPN
, 1);
2167 /*****************************************************************************/
2168 /* PowerPC 601 specific instructions (POWER bridge) */
2170 target_ulong
helper_rac(CPUPPCState
*env
, target_ulong addr
)
2174 target_ulong ret
= 0;
2176 /* We don't have to generate many instances of this instruction,
2177 * as rac is supervisor only.
2179 /* XXX: FIX THIS: Pretend we have no BAT */
2180 nb_BATs
= env
->nb_BATs
;
2182 if (get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) == 0) {
2185 env
->nb_BATs
= nb_BATs
;
2189 static inline target_ulong
booke_tlb_to_page_size(int size
)
2191 return 1024 << (2 * size
);
2194 static inline int booke_page_size_to_tlb(target_ulong page_size
)
2198 switch (page_size
) {
2232 #if defined(TARGET_PPC64)
2233 case 0x000100000000ULL
:
2236 case 0x000400000000ULL
:
2239 case 0x001000000000ULL
:
2242 case 0x004000000000ULL
:
2245 case 0x010000000000ULL
:
2257 /* Helpers for 4xx TLB management */
2258 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2260 #define PPC4XX_TLBHI_V 0x00000040
2261 #define PPC4XX_TLBHI_E 0x00000020
2262 #define PPC4XX_TLBHI_SIZE_MIN 0
2263 #define PPC4XX_TLBHI_SIZE_MAX 7
2264 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2265 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2266 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2268 #define PPC4XX_TLBLO_EX 0x00000200
2269 #define PPC4XX_TLBLO_WR 0x00000100
2270 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2271 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2273 target_ulong
helper_4xx_tlbre_hi(CPUPPCState
*env
, target_ulong entry
)
2279 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2280 tlb
= &env
->tlb
.tlbe
[entry
];
2282 if (tlb
->prot
& PAGE_VALID
) {
2283 ret
|= PPC4XX_TLBHI_V
;
2285 size
= booke_page_size_to_tlb(tlb
->size
);
2286 if (size
< PPC4XX_TLBHI_SIZE_MIN
|| size
> PPC4XX_TLBHI_SIZE_MAX
) {
2287 size
= PPC4XX_TLBHI_SIZE_DEFAULT
;
2289 ret
|= size
<< PPC4XX_TLBHI_SIZE_SHIFT
;
2290 env
->spr
[SPR_40x_PID
] = tlb
->PID
;
2294 target_ulong
helper_4xx_tlbre_lo(CPUPPCState
*env
, target_ulong entry
)
2299 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2300 tlb
= &env
->tlb
.tlbe
[entry
];
2302 if (tlb
->prot
& PAGE_EXEC
) {
2303 ret
|= PPC4XX_TLBLO_EX
;
2305 if (tlb
->prot
& PAGE_WRITE
) {
2306 ret
|= PPC4XX_TLBLO_WR
;
2311 void helper_4xx_tlbwe_hi(CPUPPCState
*env
, target_ulong entry
,
2314 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2315 CPUState
*cs
= CPU(cpu
);
2317 target_ulong page
, end
;
2319 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2321 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2322 tlb
= &env
->tlb
.tlbe
[entry
];
2323 /* Invalidate previous TLB (if it's valid) */
2324 if (tlb
->prot
& PAGE_VALID
) {
2325 end
= tlb
->EPN
+ tlb
->size
;
2326 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx
" end "
2327 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2328 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2329 tlb_flush_page(cs
, page
);
2332 tlb
->size
= booke_tlb_to_page_size((val
>> PPC4XX_TLBHI_SIZE_SHIFT
)
2333 & PPC4XX_TLBHI_SIZE_MASK
);
2334 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2335 * If this ever occurs, one should use the ppcemb target instead
2336 * of the ppc or ppc64 one
2338 if ((val
& PPC4XX_TLBHI_V
) && tlb
->size
< TARGET_PAGE_SIZE
) {
2339 cpu_abort(cs
, "TLB size " TARGET_FMT_lu
" < %u "
2340 "are not supported (%d)\n",
2341 tlb
->size
, TARGET_PAGE_SIZE
, (int)((val
>> 7) & 0x7));
2343 tlb
->EPN
= val
& ~(tlb
->size
- 1);
2344 if (val
& PPC4XX_TLBHI_V
) {
2345 tlb
->prot
|= PAGE_VALID
;
2346 if (val
& PPC4XX_TLBHI_E
) {
2347 /* XXX: TO BE FIXED */
2349 "Little-endian TLB entries are not supported by now\n");
2352 tlb
->prot
&= ~PAGE_VALID
;
2354 tlb
->PID
= env
->spr
[SPR_40x_PID
]; /* PID */
2355 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2356 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2357 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2358 tlb
->prot
& PAGE_READ
? 'r' : '-',
2359 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2360 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2361 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2362 /* Invalidate new TLB (if valid) */
2363 if (tlb
->prot
& PAGE_VALID
) {
2364 end
= tlb
->EPN
+ tlb
->size
;
2365 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx
" end "
2366 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2367 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2368 tlb_flush_page(cs
, page
);
2373 void helper_4xx_tlbwe_lo(CPUPPCState
*env
, target_ulong entry
,
2378 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2380 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2381 tlb
= &env
->tlb
.tlbe
[entry
];
2382 tlb
->attr
= val
& PPC4XX_TLBLO_ATTR_MASK
;
2383 tlb
->RPN
= val
& PPC4XX_TLBLO_RPN_MASK
;
2384 tlb
->prot
= PAGE_READ
;
2385 if (val
& PPC4XX_TLBLO_EX
) {
2386 tlb
->prot
|= PAGE_EXEC
;
2388 if (val
& PPC4XX_TLBLO_WR
) {
2389 tlb
->prot
|= PAGE_WRITE
;
2391 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2392 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2393 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2394 tlb
->prot
& PAGE_READ
? 'r' : '-',
2395 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2396 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2397 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2400 target_ulong
helper_4xx_tlbsx(CPUPPCState
*env
, target_ulong address
)
2402 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_40x_PID
]);
2405 /* PowerPC 440 TLB management */
2406 void helper_440_tlbwe(CPUPPCState
*env
, uint32_t word
, target_ulong entry
,
2409 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2411 target_ulong EPN
, RPN
, size
;
2414 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx
"\n",
2415 __func__
, word
, (int)entry
, value
);
2418 tlb
= &env
->tlb
.tlbe
[entry
];
2421 /* Just here to please gcc */
2423 EPN
= value
& 0xFFFFFC00;
2424 if ((tlb
->prot
& PAGE_VALID
) && EPN
!= tlb
->EPN
) {
2428 size
= booke_tlb_to_page_size((value
>> 4) & 0xF);
2429 if ((tlb
->prot
& PAGE_VALID
) && tlb
->size
< size
) {
2434 tlb
->attr
|= (value
>> 8) & 1;
2435 if (value
& 0x200) {
2436 tlb
->prot
|= PAGE_VALID
;
2438 if (tlb
->prot
& PAGE_VALID
) {
2439 tlb
->prot
&= ~PAGE_VALID
;
2443 tlb
->PID
= env
->spr
[SPR_440_MMUCR
] & 0x000000FF;
2444 if (do_flush_tlbs
) {
2445 tlb_flush(CPU(cpu
));
2449 RPN
= value
& 0xFFFFFC0F;
2450 if ((tlb
->prot
& PAGE_VALID
) && tlb
->RPN
!= RPN
) {
2451 tlb_flush(CPU(cpu
));
2456 tlb
->attr
= (tlb
->attr
& 0x1) | (value
& 0x0000FF00);
2457 tlb
->prot
= tlb
->prot
& PAGE_VALID
;
2459 tlb
->prot
|= PAGE_READ
<< 4;
2462 tlb
->prot
|= PAGE_WRITE
<< 4;
2465 tlb
->prot
|= PAGE_EXEC
<< 4;
2468 tlb
->prot
|= PAGE_READ
;
2471 tlb
->prot
|= PAGE_WRITE
;
2474 tlb
->prot
|= PAGE_EXEC
;
2480 target_ulong
helper_440_tlbre(CPUPPCState
*env
, uint32_t word
,
2488 tlb
= &env
->tlb
.tlbe
[entry
];
2491 /* Just here to please gcc */
2494 size
= booke_page_size_to_tlb(tlb
->size
);
2495 if (size
< 0 || size
> 0xF) {
2499 if (tlb
->attr
& 0x1) {
2502 if (tlb
->prot
& PAGE_VALID
) {
2505 env
->spr
[SPR_440_MMUCR
] &= ~0x000000FF;
2506 env
->spr
[SPR_440_MMUCR
] |= tlb
->PID
;
2512 ret
= tlb
->attr
& ~0x1;
2513 if (tlb
->prot
& (PAGE_READ
<< 4)) {
2516 if (tlb
->prot
& (PAGE_WRITE
<< 4)) {
2519 if (tlb
->prot
& (PAGE_EXEC
<< 4)) {
2522 if (tlb
->prot
& PAGE_READ
) {
2525 if (tlb
->prot
& PAGE_WRITE
) {
2528 if (tlb
->prot
& PAGE_EXEC
) {
2536 target_ulong
helper_440_tlbsx(CPUPPCState
*env
, target_ulong address
)
2538 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_440_MMUCR
] & 0xFF);
2541 /* PowerPC BookE 2.06 TLB management */
2543 static ppcmas_tlb_t
*booke206_cur_tlb(CPUPPCState
*env
)
2545 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2546 uint32_t tlbncfg
= 0;
2547 int esel
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ESEL_MASK
) >> MAS0_ESEL_SHIFT
;
2548 int ea
= (env
->spr
[SPR_BOOKE_MAS2
] & MAS2_EPN_MASK
);
2551 tlb
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2552 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlb
];
2554 if ((tlbncfg
& TLBnCFG_HES
) && (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_HES
)) {
2555 cpu_abort(CPU(cpu
), "we don't support HES yet\n");
2558 return booke206_get_tlbm(env
, tlb
, ea
, esel
);
2561 void helper_booke_setpid(CPUPPCState
*env
, uint32_t pidn
, target_ulong pid
)
2563 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2565 env
->spr
[pidn
] = pid
;
2566 /* changing PIDs mean we're in a different address space now */
2567 tlb_flush(CPU(cpu
));
2570 void helper_booke206_tlbwe(CPUPPCState
*env
)
2572 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2573 uint32_t tlbncfg
, tlbn
;
2575 uint32_t size_tlb
, size_ps
;
2579 switch (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_WQ_MASK
) {
2580 case MAS0_WQ_ALWAYS
:
2581 /* good to go, write that entry */
2584 /* XXX check if reserved */
2589 case MAS0_WQ_CLR_RSRV
:
2590 /* XXX clear entry */
2593 /* no idea what to do */
2597 if (((env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ATSEL
) == MAS0_ATSEL_LRAT
) &&
2599 /* XXX we don't support direct LRAT setting yet */
2600 fprintf(stderr
, "cpu: don't support LRAT setting yet\n");
2604 tlbn
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2605 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlbn
];
2607 tlb
= booke206_cur_tlb(env
);
2610 raise_exception_err_ra(env
, POWERPC_EXCP_PROGRAM
,
2611 POWERPC_EXCP_INVAL
|
2612 POWERPC_EXCP_INVAL_INVAL
, GETPC());
2615 /* check that we support the targeted size */
2616 size_tlb
= (env
->spr
[SPR_BOOKE_MAS1
] & MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
2617 size_ps
= booke206_tlbnps(env
, tlbn
);
2618 if ((env
->spr
[SPR_BOOKE_MAS1
] & MAS1_VALID
) && (tlbncfg
& TLBnCFG_AVAIL
) &&
2619 !(size_ps
& (1 << size_tlb
))) {
2620 raise_exception_err_ra(env
, POWERPC_EXCP_PROGRAM
,
2621 POWERPC_EXCP_INVAL
|
2622 POWERPC_EXCP_INVAL_INVAL
, GETPC());
2626 cpu_abort(CPU(cpu
), "missing HV implementation\n");
2628 tlb
->mas7_3
= ((uint64_t)env
->spr
[SPR_BOOKE_MAS7
] << 32) |
2629 env
->spr
[SPR_BOOKE_MAS3
];
2630 tlb
->mas1
= env
->spr
[SPR_BOOKE_MAS1
];
2633 if (!(tlbncfg
& TLBnCFG_AVAIL
)) {
2634 /* force !AVAIL TLB entries to correct page size */
2635 tlb
->mas1
&= ~MAS1_TSIZE_MASK
;
2636 /* XXX can be configured in MMUCSR0 */
2637 tlb
->mas1
|= (tlbncfg
& TLBnCFG_MINSIZE
) >> 12;
2640 /* Make a mask from TLB size to discard invalid bits in EPN field */
2641 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2642 /* Add a mask for page attributes */
2643 mask
|= MAS2_ACM
| MAS2_VLE
| MAS2_W
| MAS2_I
| MAS2_M
| MAS2_G
| MAS2_E
;
2646 /* Executing a tlbwe instruction in 32-bit mode will set
2647 * bits 0:31 of the TLB EPN field to zero.
2652 tlb
->mas2
= env
->spr
[SPR_BOOKE_MAS2
] & mask
;
2654 if (!(tlbncfg
& TLBnCFG_IPROT
)) {
2655 /* no IPROT supported by TLB */
2656 tlb
->mas1
&= ~MAS1_IPROT
;
2659 if (booke206_tlb_to_page_size(env
, tlb
) == TARGET_PAGE_SIZE
) {
2660 tlb_flush_page(CPU(cpu
), tlb
->mas2
& MAS2_EPN_MASK
);
2662 tlb_flush(CPU(cpu
));
2666 static inline void booke206_tlb_to_mas(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2668 int tlbn
= booke206_tlbm_to_tlbn(env
, tlb
);
2669 int way
= booke206_tlbm_to_way(env
, tlb
);
2671 env
->spr
[SPR_BOOKE_MAS0
] = tlbn
<< MAS0_TLBSEL_SHIFT
;
2672 env
->spr
[SPR_BOOKE_MAS0
] |= way
<< MAS0_ESEL_SHIFT
;
2673 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2675 env
->spr
[SPR_BOOKE_MAS1
] = tlb
->mas1
;
2676 env
->spr
[SPR_BOOKE_MAS2
] = tlb
->mas2
;
2677 env
->spr
[SPR_BOOKE_MAS3
] = tlb
->mas7_3
;
2678 env
->spr
[SPR_BOOKE_MAS7
] = tlb
->mas7_3
>> 32;
2681 void helper_booke206_tlbre(CPUPPCState
*env
)
2683 ppcmas_tlb_t
*tlb
= NULL
;
2685 tlb
= booke206_cur_tlb(env
);
2687 env
->spr
[SPR_BOOKE_MAS1
] = 0;
2689 booke206_tlb_to_mas(env
, tlb
);
2693 void helper_booke206_tlbsx(CPUPPCState
*env
, target_ulong address
)
2695 ppcmas_tlb_t
*tlb
= NULL
;
2700 spid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID_MASK
) >> MAS6_SPID_SHIFT
;
2701 sas
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
;
2703 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2704 int ways
= booke206_tlb_ways(env
, i
);
2706 for (j
= 0; j
< ways
; j
++) {
2707 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2713 if (ppcmas_tlb_check(env
, tlb
, &raddr
, address
, spid
)) {
2717 if (sas
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
2721 booke206_tlb_to_mas(env
, tlb
);
2726 /* no entry found, fill with defaults */
2727 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
2728 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
2729 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
2730 env
->spr
[SPR_BOOKE_MAS3
] = 0;
2731 env
->spr
[SPR_BOOKE_MAS7
] = 0;
2733 if (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
) {
2734 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
2737 env
->spr
[SPR_BOOKE_MAS1
] |= (env
->spr
[SPR_BOOKE_MAS6
] >> 16)
2740 /* next victim logic */
2741 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
2743 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
2744 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2747 static inline void booke206_invalidate_ea_tlb(CPUPPCState
*env
, int tlbn
,
2751 int ways
= booke206_tlb_ways(env
, tlbn
);
2754 for (i
= 0; i
< ways
; i
++) {
2755 ppcmas_tlb_t
*tlb
= booke206_get_tlbm(env
, tlbn
, ea
, i
);
2759 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2760 if (((tlb
->mas2
& MAS2_EPN_MASK
) == (ea
& mask
)) &&
2761 !(tlb
->mas1
& MAS1_IPROT
)) {
2762 tlb
->mas1
&= ~MAS1_VALID
;
2767 void helper_booke206_tlbivax(CPUPPCState
*env
, target_ulong address
)
2771 if (address
& 0x4) {
2772 /* flush all entries */
2773 if (address
& 0x8) {
2774 /* flush all of TLB1 */
2775 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB1
, 1);
2777 /* flush all of TLB0 */
2778 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB0
, 0);
2783 if (address
& 0x8) {
2784 /* flush TLB1 entries */
2785 booke206_invalidate_ea_tlb(env
, 1, address
);
2790 /* flush TLB0 entries */
2791 booke206_invalidate_ea_tlb(env
, 0, address
);
2793 tlb_flush_page(cs
, address
& MAS2_EPN_MASK
);
2798 void helper_booke206_tlbilx0(CPUPPCState
*env
, target_ulong address
)
2800 /* XXX missing LPID handling */
2801 booke206_flush_tlb(env
, -1, 1);
2804 void helper_booke206_tlbilx1(CPUPPCState
*env
, target_ulong address
)
2806 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2808 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2809 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
2812 /* XXX missing LPID handling */
2813 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2814 tlb_size
= booke206_tlb_size(env
, i
);
2815 for (j
= 0; j
< tlb_size
; j
++) {
2816 if (!(tlb
[j
].mas1
& MAS1_IPROT
) &&
2817 ((tlb
[j
].mas1
& MAS1_TID_MASK
) == tid
)) {
2818 tlb
[j
].mas1
&= ~MAS1_VALID
;
2821 tlb
+= booke206_tlb_size(env
, i
);
2823 tlb_flush(CPU(cpu
));
2826 void helper_booke206_tlbilx3(CPUPPCState
*env
, target_ulong address
)
2828 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2831 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2832 int pid
= tid
>> MAS6_SPID_SHIFT
;
2833 int sgs
= env
->spr
[SPR_BOOKE_MAS5
] & MAS5_SGS
;
2834 int ind
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SIND
) ? MAS1_IND
: 0;
2835 /* XXX check for unsupported isize and raise an invalid opcode then */
2836 int size
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_ISIZE_MASK
;
2837 /* XXX implement MAV2 handling */
2840 /* XXX missing LPID handling */
2841 /* flush by pid and ea */
2842 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2843 int ways
= booke206_tlb_ways(env
, i
);
2845 for (j
= 0; j
< ways
; j
++) {
2846 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2850 if ((ppcmas_tlb_check(env
, tlb
, NULL
, address
, pid
) != 0) ||
2851 (tlb
->mas1
& MAS1_IPROT
) ||
2852 ((tlb
->mas1
& MAS1_IND
) != ind
) ||
2853 ((tlb
->mas8
& MAS8_TGS
) != sgs
)) {
2856 if (mav2
&& ((tlb
->mas1
& MAS1_TSIZE_MASK
) != size
)) {
2857 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2860 /* XXX e500mc doesn't match SAS, but other cores might */
2861 tlb
->mas1
&= ~MAS1_VALID
;
2864 tlb_flush(CPU(cpu
));
2867 void helper_booke206_tlbflush(CPUPPCState
*env
, target_ulong type
)
2872 flags
|= BOOKE206_FLUSH_TLB1
;
2876 flags
|= BOOKE206_FLUSH_TLB0
;
2879 booke206_flush_tlb(env
, flags
, 1);
2883 void helper_check_tlb_flush_local(CPUPPCState
*env
)
2885 check_tlb_flush(env
, false);
2888 void helper_check_tlb_flush_global(CPUPPCState
*env
)
2890 check_tlb_flush(env
, true);
2893 /*****************************************************************************/
2895 /* try to fill the TLB and return an exception if error. If retaddr is
2896 NULL, it means that the function was called in C code (i.e. not
2897 from generated code or from helper.c) */
2898 /* XXX: fix it to restore all registers */
2899 void tlb_fill(CPUState
*cs
, target_ulong addr
, MMUAccessType access_type
,
2900 int mmu_idx
, uintptr_t retaddr
)
2902 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
2903 PowerPCCPUClass
*pcc
= POWERPC_CPU_GET_CLASS(cs
);
2904 CPUPPCState
*env
= &cpu
->env
;
2907 if (pcc
->handle_mmu_fault
) {
2908 ret
= pcc
->handle_mmu_fault(cpu
, addr
, access_type
, mmu_idx
);
2910 ret
= cpu_ppc_handle_mmu_fault(env
, addr
, access_type
, mmu_idx
);
2912 if (unlikely(ret
!= 0)) {
2913 raise_exception_err_ra(env
, cs
->exception_index
, env
->error_code
,