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/>.
21 #include "sysemu/kvm.h"
23 #include "mmu-hash64.h"
24 #include "mmu-hash32.h"
28 //#define DEBUG_SOFTWARE_TLB
29 //#define DUMP_PAGE_TABLES
30 //#define DEBUG_SOFTWARE_TLB
31 //#define FLUSH_ALL_TLBS
34 # define LOG_MMU(...) qemu_log(__VA_ARGS__)
35 # define LOG_MMU_STATE(env) log_cpu_state((env), 0)
37 # define LOG_MMU(...) do { } while (0)
38 # define LOG_MMU_STATE(...) do { } while (0)
41 #ifdef DEBUG_SOFTWARE_TLB
42 # define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
44 # define LOG_SWTLB(...) do { } while (0)
48 # define LOG_BATS(...) qemu_log(__VA_ARGS__)
50 # define LOG_BATS(...) do { } while (0)
53 /*****************************************************************************/
54 /* PowerPC MMU emulation */
55 #if defined(CONFIG_USER_ONLY)
56 int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
, int rw
,
59 int exception
, error_code
;
62 exception
= POWERPC_EXCP_ISI
;
63 error_code
= 0x40000000;
65 exception
= POWERPC_EXCP_DSI
;
66 error_code
= 0x40000000;
68 error_code
|= 0x02000000;
70 env
->spr
[SPR_DAR
] = address
;
71 env
->spr
[SPR_DSISR
] = error_code
;
73 env
->exception_index
= exception
;
74 env
->error_code
= error_code
;
80 /* Common routines used by software and hardware TLBs emulation */
81 static inline int pte_is_valid(target_ulong pte0
)
83 return pte0
& 0x80000000 ? 1 : 0;
86 static inline void pte_invalidate(target_ulong
*pte0
)
91 #define PTE_PTEM_MASK 0x7FFFFFBF
92 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
94 int pp_check(int key
, int pp
, int nx
)
98 /* Compute access rights */
99 /* When pp is 3/7, the result is undefined. Set it to noaccess */
106 access
|= PAGE_WRITE
;
124 access
= PAGE_READ
| PAGE_WRITE
;
135 int check_prot(int prot
, int rw
, int access_type
)
139 if (access_type
== ACCESS_CODE
) {
140 if (prot
& PAGE_EXEC
) {
146 if (prot
& PAGE_WRITE
) {
152 if (prot
& PAGE_READ
) {
162 static inline int ppc6xx_tlb_pte_check(mmu_ctx_t
*ctx
, target_ulong pte0
,
163 target_ulong pte1
, int h
, int rw
, int type
)
165 target_ulong ptem
, mmask
;
166 int access
, ret
, pteh
, ptev
, pp
;
169 /* Check validity and table match */
170 ptev
= pte_is_valid(pte0
);
171 pteh
= (pte0
>> 6) & 1;
172 if (ptev
&& h
== pteh
) {
173 /* Check vsid & api */
174 ptem
= pte0
& PTE_PTEM_MASK
;
175 mmask
= PTE_CHECK_MASK
;
176 pp
= pte1
& 0x00000003;
177 if (ptem
== ctx
->ptem
) {
178 if (ctx
->raddr
!= (hwaddr
)-1ULL) {
179 /* all matches should have equal RPN, WIMG & PP */
180 if ((ctx
->raddr
& mmask
) != (pte1
& mmask
)) {
181 qemu_log("Bad RPN/WIMG/PP\n");
185 /* Compute access rights */
186 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
187 /* Keep the matching PTE informations */
190 ret
= check_prot(ctx
->prot
, rw
, type
);
193 LOG_MMU("PTE access granted !\n");
195 /* Access right violation */
196 LOG_MMU("PTE access rejected\n");
204 int pte_update_flags(mmu_ctx_t
*ctx
, target_ulong
*pte1p
,
209 /* Update page flags */
210 if (!(*pte1p
& 0x00000100)) {
211 /* Update accessed flag */
212 *pte1p
|= 0x00000100;
215 if (!(*pte1p
& 0x00000080)) {
216 if (rw
== 1 && ret
== 0) {
217 /* Update changed flag */
218 *pte1p
|= 0x00000080;
221 /* Force page fault for first write access */
222 ctx
->prot
&= ~PAGE_WRITE
;
229 /* Software driven TLB helpers */
230 static inline int ppc6xx_tlb_getnum(CPUPPCState
*env
, target_ulong eaddr
,
231 int way
, int is_code
)
235 /* Select TLB num in a way from address */
236 nr
= (eaddr
>> TARGET_PAGE_BITS
) & (env
->tlb_per_way
- 1);
238 nr
+= env
->tlb_per_way
* way
;
239 /* 6xx have separate TLBs for instructions and data */
240 if (is_code
&& env
->id_tlbs
== 1) {
247 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState
*env
)
252 /* LOG_SWTLB("Invalidate all TLBs\n"); */
253 /* Invalidate all defined software TLB */
255 if (env
->id_tlbs
== 1) {
258 for (nr
= 0; nr
< max
; nr
++) {
259 tlb
= &env
->tlb
.tlb6
[nr
];
260 pte_invalidate(&tlb
->pte0
);
265 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState
*env
,
267 int is_code
, int match_epn
)
269 #if !defined(FLUSH_ALL_TLBS)
273 /* Invalidate ITLB + DTLB, all ways */
274 for (way
= 0; way
< env
->nb_ways
; way
++) {
275 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
, is_code
);
276 tlb
= &env
->tlb
.tlb6
[nr
];
277 if (pte_is_valid(tlb
->pte0
) && (match_epn
== 0 || eaddr
== tlb
->EPN
)) {
278 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx
"\n", nr
,
280 pte_invalidate(&tlb
->pte0
);
281 tlb_flush_page(env
, tlb
->EPN
);
285 /* XXX: PowerPC specification say this is valid as well */
286 ppc6xx_tlb_invalidate_all(env
);
290 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState
*env
,
291 target_ulong eaddr
, int is_code
)
293 ppc6xx_tlb_invalidate_virt2(env
, eaddr
, is_code
, 0);
296 static void ppc6xx_tlb_store(CPUPPCState
*env
, target_ulong EPN
, int way
,
297 int is_code
, target_ulong pte0
, target_ulong pte1
)
302 nr
= ppc6xx_tlb_getnum(env
, EPN
, way
, is_code
);
303 tlb
= &env
->tlb
.tlb6
[nr
];
304 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
305 " PTE1 " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
, EPN
, pte0
, pte1
);
306 /* Invalidate any pending reference in QEMU for this virtual address */
307 ppc6xx_tlb_invalidate_virt2(env
, EPN
, is_code
, 1);
311 /* Store last way for LRU mechanism */
315 static inline int ppc6xx_tlb_check(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
316 target_ulong eaddr
, int rw
, int access_type
)
323 ret
= -1; /* No TLB found */
324 for (way
= 0; way
< env
->nb_ways
; way
++) {
325 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
,
326 access_type
== ACCESS_CODE
? 1 : 0);
327 tlb
= &env
->tlb
.tlb6
[nr
];
328 /* This test "emulates" the PTE index match for hardware TLBs */
329 if ((eaddr
& TARGET_PAGE_MASK
) != tlb
->EPN
) {
330 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx
" " TARGET_FMT_lx
331 "] <> " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
,
332 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
333 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
, eaddr
);
336 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx
" <> " TARGET_FMT_lx
" "
337 TARGET_FMT_lx
" %c %c\n", nr
, env
->nb_tlb
,
338 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
339 tlb
->EPN
, eaddr
, tlb
->pte1
,
340 rw
? 'S' : 'L', access_type
== ACCESS_CODE
? 'I' : 'D');
341 switch (ppc6xx_tlb_pte_check(ctx
, tlb
->pte0
, tlb
->pte1
, 0, rw
, access_type
)) {
343 /* TLB inconsistency */
346 /* Access violation */
356 /* XXX: we should go on looping to check all TLBs consistency
357 * but we can speed-up the whole thing as the
358 * result would be undefined if TLBs are not consistent.
367 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx
" prot=%01x ret=%d\n",
368 ctx
->raddr
& TARGET_PAGE_MASK
, ctx
->prot
, ret
);
369 /* Update page flags */
370 pte_update_flags(ctx
, &env
->tlb
.tlb6
[best
].pte1
, ret
, rw
);
376 /* Perform BAT hit & translation */
377 static inline void bat_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
378 int *validp
, int *protp
, target_ulong
*BATu
,
384 bl
= (*BATu
& 0x00001FFC) << 15;
387 if (((msr_pr
== 0) && (*BATu
& 0x00000002)) ||
388 ((msr_pr
!= 0) && (*BATu
& 0x00000001))) {
390 pp
= *BATl
& 0x00000003;
392 prot
= PAGE_READ
| PAGE_EXEC
;
403 static inline void bat_601_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
404 int *validp
, int *protp
,
405 target_ulong
*BATu
, target_ulong
*BATl
)
408 int key
, pp
, valid
, prot
;
410 bl
= (*BATl
& 0x0000003F) << 17;
411 LOG_BATS("b %02x ==> bl " TARGET_FMT_lx
" msk " TARGET_FMT_lx
"\n",
412 (uint8_t)(*BATl
& 0x0000003F), bl
, ~bl
);
414 valid
= (*BATl
>> 6) & 1;
416 pp
= *BATu
& 0x00000003;
418 key
= (*BATu
>> 3) & 1;
420 key
= (*BATu
>> 2) & 1;
422 prot
= pp_check(key
, pp
, 0);
429 static inline int get_bat(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
430 target_ulong
virtual, int rw
, int type
)
432 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
433 target_ulong BEPIl
, BEPIu
, bl
;
437 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx
"\n", __func__
,
438 type
== ACCESS_CODE
? 'I' : 'D', virtual);
441 BATlt
= env
->IBAT
[1];
442 BATut
= env
->IBAT
[0];
445 BATlt
= env
->DBAT
[1];
446 BATut
= env
->DBAT
[0];
449 for (i
= 0; i
< env
->nb_BATs
; i
++) {
452 BEPIu
= *BATu
& 0xF0000000;
453 BEPIl
= *BATu
& 0x0FFE0000;
454 if (unlikely(env
->mmu_model
== POWERPC_MMU_601
)) {
455 bat_601_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
457 bat_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
459 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
460 " BATl " TARGET_FMT_lx
"\n", __func__
,
461 type
== ACCESS_CODE
? 'I' : 'D', i
, virtual, *BATu
, *BATl
);
462 if ((virtual & 0xF0000000) == BEPIu
&&
463 ((virtual & 0x0FFE0000) & ~bl
) == BEPIl
) {
466 /* Get physical address */
467 ctx
->raddr
= (*BATl
& 0xF0000000) |
468 ((virtual & 0x0FFE0000 & bl
) | (*BATl
& 0x0FFE0000)) |
469 (virtual & 0x0001F000);
470 /* Compute access rights */
472 ret
= check_prot(ctx
->prot
, rw
, type
);
474 LOG_BATS("BAT %d match: r " TARGET_FMT_plx
" prot=%c%c\n",
475 i
, ctx
->raddr
, ctx
->prot
& PAGE_READ
? 'R' : '-',
476 ctx
->prot
& PAGE_WRITE
? 'W' : '-');
483 #if defined(DEBUG_BATS)
484 if (qemu_log_enabled()) {
485 LOG_BATS("no BAT match for " TARGET_FMT_lx
":\n", virtual);
486 for (i
= 0; i
< 4; i
++) {
489 BEPIu
= *BATu
& 0xF0000000;
490 BEPIl
= *BATu
& 0x0FFE0000;
491 bl
= (*BATu
& 0x00001FFC) << 15;
492 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
493 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
494 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
495 __func__
, type
== ACCESS_CODE
? 'I' : 'D', i
, virtual,
496 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
505 hwaddr
get_pteg_offset(CPUPPCState
*env
, hwaddr hash
, int pte_size
)
507 return (hash
* pte_size
* 8) & env
->htab_mask
;
510 static inline int find_pte(CPUPPCState
*env
, mmu_ctx_t
*ctx
, int h
, int rw
,
511 int type
, int target_page_bits
)
513 #if defined(TARGET_PPC64)
514 if (env
->mmu_model
& POWERPC_MMU_64
) {
515 return find_pte64(env
, ctx
, h
, rw
, type
, target_page_bits
);
519 return find_pte32(env
, ctx
, h
, rw
, type
, target_page_bits
);
522 /* Perform segment based translation */
523 static inline int get_segment(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
524 target_ulong eaddr
, int rw
, int type
)
528 int ds
, pr
, target_page_bits
;
533 #if defined(TARGET_PPC64)
534 if (env
->mmu_model
& POWERPC_MMU_64
) {
536 target_ulong pageaddr
;
539 LOG_MMU("Check SLBs\n");
540 slb
= slb_lookup(env
, eaddr
);
545 if (slb
->vsid
& SLB_VSID_B
) {
546 vsid
= (slb
->vsid
& SLB_VSID_VSID
) >> SLB_VSID_SHIFT_1T
;
549 vsid
= (slb
->vsid
& SLB_VSID_VSID
) >> SLB_VSID_SHIFT
;
553 target_page_bits
= (slb
->vsid
& SLB_VSID_L
)
554 ? TARGET_PAGE_BITS_16M
: TARGET_PAGE_BITS
;
555 ctx
->key
= !!(pr
? (slb
->vsid
& SLB_VSID_KP
)
556 : (slb
->vsid
& SLB_VSID_KS
));
558 ctx
->nx
= !!(slb
->vsid
& SLB_VSID_N
);
560 pageaddr
= eaddr
& ((1ULL << segment_bits
)
561 - (1ULL << target_page_bits
));
562 if (slb
->vsid
& SLB_VSID_B
) {
563 hash
= vsid
^ (vsid
<< 25) ^ (pageaddr
>> target_page_bits
);
565 hash
= vsid
^ (pageaddr
>> target_page_bits
);
567 /* Only 5 bits of the page index are used in the AVPN */
568 ctx
->ptem
= (slb
->vsid
& SLB_VSID_PTEM
) |
569 ((pageaddr
>> 16) & ((1ULL << segment_bits
) - 0x80));
571 #endif /* defined(TARGET_PPC64) */
573 target_ulong sr
, pgidx
;
575 sr
= env
->sr
[eaddr
>> 28];
576 ctx
->key
= (((sr
& 0x20000000) && (pr
!= 0)) ||
577 ((sr
& 0x40000000) && (pr
== 0))) ? 1 : 0;
578 ds
= sr
& 0x80000000 ? 1 : 0;
579 ctx
->nx
= sr
& 0x10000000 ? 1 : 0;
580 vsid
= sr
& 0x00FFFFFF;
581 target_page_bits
= TARGET_PAGE_BITS
;
582 LOG_MMU("Check segment v=" TARGET_FMT_lx
" %d " TARGET_FMT_lx
" nip="
583 TARGET_FMT_lx
" lr=" TARGET_FMT_lx
584 " ir=%d dr=%d pr=%d %d t=%d\n",
585 eaddr
, (int)(eaddr
>> 28), sr
, env
->nip
, env
->lr
, (int)msr_ir
,
586 (int)msr_dr
, pr
!= 0 ? 1 : 0, rw
, type
);
587 pgidx
= (eaddr
& ~SEGMENT_MASK_256M
) >> target_page_bits
;
589 ctx
->ptem
= (vsid
<< 7) | (pgidx
>> 10);
591 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx
"\n",
592 ctx
->key
, ds
, ctx
->nx
, vsid
);
595 /* Check if instruction fetch is allowed, if needed */
596 if (type
!= ACCESS_CODE
|| ctx
->nx
== 0) {
597 /* Page address translation */
598 LOG_MMU("htab_base " TARGET_FMT_plx
" htab_mask " TARGET_FMT_plx
599 " hash " TARGET_FMT_plx
"\n",
600 env
->htab_base
, env
->htab_mask
, hash
);
602 ctx
->hash
[1] = ~hash
;
604 /* Initialize real address with an invalid value */
605 ctx
->raddr
= (hwaddr
)-1ULL;
606 if (unlikely(env
->mmu_model
== POWERPC_MMU_SOFT_6xx
||
607 env
->mmu_model
== POWERPC_MMU_SOFT_74xx
)) {
608 /* Software TLB search */
609 ret
= ppc6xx_tlb_check(env
, ctx
, eaddr
, rw
, type
);
611 LOG_MMU("0 htab=" TARGET_FMT_plx
"/" TARGET_FMT_plx
612 " vsid=" TARGET_FMT_lx
" ptem=" TARGET_FMT_lx
613 " hash=" TARGET_FMT_plx
"\n",
614 env
->htab_base
, env
->htab_mask
, vsid
, ctx
->ptem
,
616 /* Primary table lookup */
617 ret
= find_pte(env
, ctx
, 0, rw
, type
, target_page_bits
);
619 /* Secondary table lookup */
620 LOG_MMU("1 htab=" TARGET_FMT_plx
"/" TARGET_FMT_plx
621 " vsid=" TARGET_FMT_lx
" api=" TARGET_FMT_lx
622 " hash=" TARGET_FMT_plx
"\n", env
->htab_base
,
623 env
->htab_mask
, vsid
, ctx
->ptem
, ctx
->hash
[1]);
624 ret2
= find_pte(env
, ctx
, 1, rw
, type
,
631 #if defined(DUMP_PAGE_TABLES)
632 if (qemu_log_enabled()) {
634 uint32_t a0
, a1
, a2
, a3
;
636 qemu_log("Page table: " TARGET_FMT_plx
" len " TARGET_FMT_plx
637 "\n", sdr
, mask
+ 0x80);
638 for (curaddr
= sdr
; curaddr
< (sdr
+ mask
+ 0x80);
640 a0
= ldl_phys(curaddr
);
641 a1
= ldl_phys(curaddr
+ 4);
642 a2
= ldl_phys(curaddr
+ 8);
643 a3
= ldl_phys(curaddr
+ 12);
644 if (a0
!= 0 || a1
!= 0 || a2
!= 0 || a3
!= 0) {
645 qemu_log(TARGET_FMT_plx
": %08x %08x %08x %08x\n",
646 curaddr
, a0
, a1
, a2
, a3
);
652 LOG_MMU("No access allowed\n");
658 LOG_MMU("direct store...\n");
659 /* Direct-store segment : absolutely *BUGGY* for now */
661 /* Direct-store implies a 32-bit MMU.
662 * Check the Segment Register's bus unit ID (BUID).
664 sr
= env
->sr
[eaddr
>> 28];
665 if ((sr
& 0x1FF00000) >> 20 == 0x07f) {
666 /* Memory-forced I/O controller interface access */
667 /* If T=1 and BUID=x'07F', the 601 performs a memory access
668 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
670 ctx
->raddr
= ((sr
& 0xF) << 28) | (eaddr
& 0x0FFFFFFF);
671 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
677 /* Integer load/store : only access allowed */
680 /* No code fetch is allowed in direct-store areas */
683 /* Floating point load/store */
686 /* lwarx, ldarx or srwcx. */
689 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
690 /* Should make the instruction do no-op.
691 * As it already do no-op, it's quite easy :-)
699 qemu_log("ERROR: instruction should not need "
700 "address translation\n");
703 if ((rw
== 1 || ctx
->key
!= 1) && (rw
== 0 || ctx
->key
!= 0)) {
714 /* Generic TLB check function for embedded PowerPC implementations */
715 static int ppcemb_tlb_check(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
717 target_ulong address
, uint32_t pid
, int ext
,
722 /* Check valid flag */
723 if (!(tlb
->prot
& PAGE_VALID
)) {
726 mask
= ~(tlb
->size
- 1);
727 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx
" PID %u <=> " TARGET_FMT_lx
728 " " TARGET_FMT_lx
" %u %x\n", __func__
, i
, address
, pid
, tlb
->EPN
,
729 mask
, (uint32_t)tlb
->PID
, tlb
->prot
);
731 if (tlb
->PID
!= 0 && tlb
->PID
!= pid
) {
734 /* Check effective address */
735 if ((address
& mask
) != tlb
->EPN
) {
738 *raddrp
= (tlb
->RPN
& mask
) | (address
& ~mask
);
740 /* Extend the physical address to 36 bits */
741 *raddrp
|= (uint64_t)(tlb
->RPN
& 0xF) << 32;
747 /* Generic TLB search function for PowerPC embedded implementations */
748 static int ppcemb_tlb_search(CPUPPCState
*env
, target_ulong address
,
755 /* Default return value is no match */
757 for (i
= 0; i
< env
->nb_tlb
; i
++) {
758 tlb
= &env
->tlb
.tlbe
[i
];
759 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
, pid
, 0, i
) == 0) {
768 /* Helpers specific to PowerPC 40x implementations */
769 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState
*env
)
774 for (i
= 0; i
< env
->nb_tlb
; i
++) {
775 tlb
= &env
->tlb
.tlbe
[i
];
776 tlb
->prot
&= ~PAGE_VALID
;
781 static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState
*env
,
782 target_ulong eaddr
, uint32_t pid
)
784 #if !defined(FLUSH_ALL_TLBS)
787 target_ulong page
, end
;
790 for (i
= 0; i
< env
->nb_tlb
; i
++) {
791 tlb
= &env
->tlb
.tlbe
[i
];
792 if (ppcemb_tlb_check(env
, tlb
, &raddr
, eaddr
, pid
, 0, i
) == 0) {
793 end
= tlb
->EPN
+ tlb
->size
;
794 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
795 tlb_flush_page(env
, page
);
797 tlb
->prot
&= ~PAGE_VALID
;
802 ppc4xx_tlb_invalidate_all(env
);
806 static int mmu40x_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
807 target_ulong address
, int rw
,
812 int i
, ret
, zsel
, zpr
, pr
;
815 raddr
= (hwaddr
)-1ULL;
817 for (i
= 0; i
< env
->nb_tlb
; i
++) {
818 tlb
= &env
->tlb
.tlbe
[i
];
819 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
820 env
->spr
[SPR_40x_PID
], 0, i
) < 0) {
823 zsel
= (tlb
->attr
>> 4) & 0xF;
824 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (30 - (2 * zsel
))) & 0x3;
825 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
826 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
827 /* Check execute enable bit */
835 /* All accesses granted */
836 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
841 /* Raise Zone protection fault. */
842 env
->spr
[SPR_40x_ESR
] = 1 << 22;
850 /* Check from TLB entry */
851 ctx
->prot
= tlb
->prot
;
852 ret
= check_prot(ctx
->prot
, rw
, access_type
);
854 env
->spr
[SPR_40x_ESR
] = 0;
860 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
861 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
866 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
867 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
872 void store_40x_sler(CPUPPCState
*env
, uint32_t val
)
874 /* XXX: TO BE FIXED */
875 if (val
!= 0x00000000) {
876 cpu_abort(env
, "Little-endian regions are not supported by now\n");
878 env
->spr
[SPR_405_SLER
] = val
;
881 static inline int mmubooke_check_tlb(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
882 hwaddr
*raddr
, int *prot
,
883 target_ulong address
, int rw
,
884 int access_type
, int i
)
888 if (ppcemb_tlb_check(env
, tlb
, raddr
, address
,
889 env
->spr
[SPR_BOOKE_PID
],
890 !env
->nb_pids
, i
) >= 0) {
894 if (env
->spr
[SPR_BOOKE_PID1
] &&
895 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
896 env
->spr
[SPR_BOOKE_PID1
], 0, i
) >= 0) {
900 if (env
->spr
[SPR_BOOKE_PID2
] &&
901 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
902 env
->spr
[SPR_BOOKE_PID2
], 0, i
) >= 0) {
906 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
912 prot2
= tlb
->prot
& 0xF;
914 prot2
= (tlb
->prot
>> 4) & 0xF;
917 /* Check the address space */
918 if (access_type
== ACCESS_CODE
) {
919 if (msr_ir
!= (tlb
->attr
& 1)) {
920 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
925 if (prot2
& PAGE_EXEC
) {
926 LOG_SWTLB("%s: good TLB!\n", __func__
);
930 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
933 if (msr_dr
!= (tlb
->attr
& 1)) {
934 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
939 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
940 LOG_SWTLB("%s: found TLB!\n", __func__
);
944 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
951 static int mmubooke_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
952 target_ulong address
, int rw
,
960 raddr
= (hwaddr
)-1ULL;
961 for (i
= 0; i
< env
->nb_tlb
; i
++) {
962 tlb
= &env
->tlb
.tlbe
[i
];
963 ret
= mmubooke_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
, rw
,
972 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
973 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
976 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
977 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
983 static void booke206_flush_tlb(CPUPPCState
*env
, int flags
,
984 const int check_iprot
)
988 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
990 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
991 if (flags
& (1 << i
)) {
992 tlb_size
= booke206_tlb_size(env
, i
);
993 for (j
= 0; j
< tlb_size
; j
++) {
994 if (!check_iprot
|| !(tlb
[j
].mas1
& MAS1_IPROT
)) {
995 tlb
[j
].mas1
&= ~MAS1_VALID
;
999 tlb
+= booke206_tlb_size(env
, i
);
1005 static hwaddr
booke206_tlb_to_page_size(CPUPPCState
*env
,
1010 tlbm_size
= (tlb
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1012 return 1024ULL << tlbm_size
;
1015 /* TLB check function for MAS based SoftTLBs */
1016 static int ppcmas_tlb_check(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
1018 target_ulong address
, uint32_t pid
)
1023 /* Check valid flag */
1024 if (!(tlb
->mas1
& MAS1_VALID
)) {
1028 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
1029 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx
" PID=0x%x MAS1=0x%x MAS2=0x%"
1030 PRIx64
" mask=0x" TARGET_FMT_lx
" MAS7_3=0x%" PRIx64
" MAS8=%x\n",
1031 __func__
, address
, pid
, tlb
->mas1
, tlb
->mas2
, mask
, tlb
->mas7_3
,
1035 tlb_pid
= (tlb
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
;
1036 if (tlb_pid
!= 0 && tlb_pid
!= pid
) {
1040 /* Check effective address */
1041 if ((address
& mask
) != (tlb
->mas2
& MAS2_EPN_MASK
)) {
1046 *raddrp
= (tlb
->mas7_3
& mask
) | (address
& ~mask
);
1052 static int mmubooke206_check_tlb(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
1053 hwaddr
*raddr
, int *prot
,
1054 target_ulong address
, int rw
,
1060 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
,
1061 env
->spr
[SPR_BOOKE_PID
]) >= 0) {
1065 if (env
->spr
[SPR_BOOKE_PID1
] &&
1066 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
1067 env
->spr
[SPR_BOOKE_PID1
]) >= 0) {
1071 if (env
->spr
[SPR_BOOKE_PID2
] &&
1072 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
1073 env
->spr
[SPR_BOOKE_PID2
]) >= 0) {
1077 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
1083 if (tlb
->mas7_3
& MAS3_UR
) {
1086 if (tlb
->mas7_3
& MAS3_UW
) {
1087 prot2
|= PAGE_WRITE
;
1089 if (tlb
->mas7_3
& MAS3_UX
) {
1093 if (tlb
->mas7_3
& MAS3_SR
) {
1096 if (tlb
->mas7_3
& MAS3_SW
) {
1097 prot2
|= PAGE_WRITE
;
1099 if (tlb
->mas7_3
& MAS3_SX
) {
1104 /* Check the address space and permissions */
1105 if (access_type
== ACCESS_CODE
) {
1106 if (msr_ir
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1107 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1112 if (prot2
& PAGE_EXEC
) {
1113 LOG_SWTLB("%s: good TLB!\n", __func__
);
1117 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
1120 if (msr_dr
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1121 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1126 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
1127 LOG_SWTLB("%s: found TLB!\n", __func__
);
1131 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
1138 static int mmubooke206_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1139 target_ulong address
, int rw
,
1147 raddr
= (hwaddr
)-1ULL;
1149 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1150 int ways
= booke206_tlb_ways(env
, i
);
1152 for (j
= 0; j
< ways
; j
++) {
1153 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
1157 ret
= mmubooke206_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
,
1169 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
1170 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1173 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
1174 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
1180 static const char *book3e_tsize_to_str
[32] = {
1181 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1182 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1183 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1187 static void mmubooke_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1190 ppcemb_tlb_t
*entry
;
1193 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1194 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1198 cpu_fprintf(f
, "\nTLB:\n");
1199 cpu_fprintf(f
, "Effective Physical Size PID Prot "
1202 entry
= &env
->tlb
.tlbe
[0];
1203 for (i
= 0; i
< env
->nb_tlb
; i
++, entry
++) {
1206 uint64_t size
= (uint64_t)entry
->size
;
1209 /* Check valid flag */
1210 if (!(entry
->prot
& PAGE_VALID
)) {
1214 mask
= ~(entry
->size
- 1);
1215 ea
= entry
->EPN
& mask
;
1216 pa
= entry
->RPN
& mask
;
1217 /* Extend the physical address to 36 bits */
1218 pa
|= (hwaddr
)(entry
->RPN
& 0xF) << 32;
1221 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"M", size
/ 1024);
1223 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"k", size
);
1225 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %s %-5u %08x %08x\n",
1226 (uint64_t)ea
, (uint64_t)pa
, size_buf
, (uint32_t)entry
->PID
,
1227 entry
->prot
, entry
->attr
);
1232 static void mmubooke206_dump_one_tlb(FILE *f
, fprintf_function cpu_fprintf
,
1233 CPUPPCState
*env
, int tlbn
, int offset
,
1236 ppcmas_tlb_t
*entry
;
1239 cpu_fprintf(f
, "\nTLB%d:\n", tlbn
);
1240 cpu_fprintf(f
, "Effective Physical Size TID TS SRWX"
1241 " URWX WIMGE U0123\n");
1243 entry
= &env
->tlb
.tlbm
[offset
];
1244 for (i
= 0; i
< tlbsize
; i
++, entry
++) {
1245 hwaddr ea
, pa
, size
;
1248 if (!(entry
->mas1
& MAS1_VALID
)) {
1252 tsize
= (entry
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1253 size
= 1024ULL << tsize
;
1254 ea
= entry
->mas2
& ~(size
- 1);
1255 pa
= entry
->mas7_3
& ~(size
- 1);
1257 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %4s %-5u %1u S%c%c%c"
1258 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1259 (uint64_t)ea
, (uint64_t)pa
,
1260 book3e_tsize_to_str
[tsize
],
1261 (entry
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
,
1262 (entry
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
,
1263 entry
->mas7_3
& MAS3_SR
? 'R' : '-',
1264 entry
->mas7_3
& MAS3_SW
? 'W' : '-',
1265 entry
->mas7_3
& MAS3_SX
? 'X' : '-',
1266 entry
->mas7_3
& MAS3_UR
? 'R' : '-',
1267 entry
->mas7_3
& MAS3_UW
? 'W' : '-',
1268 entry
->mas7_3
& MAS3_UX
? 'X' : '-',
1269 entry
->mas2
& MAS2_W
? 'W' : '-',
1270 entry
->mas2
& MAS2_I
? 'I' : '-',
1271 entry
->mas2
& MAS2_M
? 'M' : '-',
1272 entry
->mas2
& MAS2_G
? 'G' : '-',
1273 entry
->mas2
& MAS2_E
? 'E' : '-',
1274 entry
->mas7_3
& MAS3_U0
? '0' : '-',
1275 entry
->mas7_3
& MAS3_U1
? '1' : '-',
1276 entry
->mas7_3
& MAS3_U2
? '2' : '-',
1277 entry
->mas7_3
& MAS3_U3
? '3' : '-');
1281 static void mmubooke206_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1287 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1288 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1292 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1293 int size
= booke206_tlb_size(env
, i
);
1299 mmubooke206_dump_one_tlb(f
, cpu_fprintf
, env
, i
, offset
, size
);
1304 void dump_mmu(FILE *f
, fprintf_function cpu_fprintf
, CPUPPCState
*env
)
1306 switch (env
->mmu_model
) {
1307 case POWERPC_MMU_BOOKE
:
1308 mmubooke_dump_mmu(f
, cpu_fprintf
, env
);
1310 case POWERPC_MMU_BOOKE206
:
1311 mmubooke206_dump_mmu(f
, cpu_fprintf
, env
);
1313 #if defined(TARGET_PPC64)
1314 case POWERPC_MMU_64B
:
1315 case POWERPC_MMU_2_06
:
1316 case POWERPC_MMU_2_06d
:
1317 dump_slb(f
, cpu_fprintf
, env
);
1321 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented\n", __func__
);
1325 static inline int check_physical(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1326 target_ulong eaddr
, int rw
)
1331 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1333 switch (env
->mmu_model
) {
1334 case POWERPC_MMU_32B
:
1335 case POWERPC_MMU_601
:
1336 case POWERPC_MMU_SOFT_6xx
:
1337 case POWERPC_MMU_SOFT_74xx
:
1338 case POWERPC_MMU_SOFT_4xx
:
1339 case POWERPC_MMU_REAL
:
1340 case POWERPC_MMU_BOOKE
:
1341 ctx
->prot
|= PAGE_WRITE
;
1343 #if defined(TARGET_PPC64)
1344 case POWERPC_MMU_64B
:
1345 case POWERPC_MMU_2_06
:
1346 case POWERPC_MMU_2_06d
:
1347 /* Real address are 60 bits long */
1348 ctx
->raddr
&= 0x0FFFFFFFFFFFFFFFULL
;
1349 ctx
->prot
|= PAGE_WRITE
;
1352 case POWERPC_MMU_SOFT_4xx_Z
:
1353 if (unlikely(msr_pe
!= 0)) {
1354 /* 403 family add some particular protections,
1355 * using PBL/PBU registers for accesses with no translation.
1358 /* Check PLB validity */
1359 (env
->pb
[0] < env
->pb
[1] &&
1360 /* and address in plb area */
1361 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1362 (env
->pb
[2] < env
->pb
[3] &&
1363 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1364 if (in_plb
^ msr_px
) {
1365 /* Access in protected area */
1367 /* Access is not allowed */
1371 /* Read-write access is allowed */
1372 ctx
->prot
|= PAGE_WRITE
;
1376 case POWERPC_MMU_MPC8xx
:
1378 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1380 case POWERPC_MMU_BOOKE206
:
1381 cpu_abort(env
, "BookE 2.06 MMU doesn't have physical real mode\n");
1384 cpu_abort(env
, "Unknown or invalid MMU model\n");
1391 static int get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1392 target_ulong eaddr
, int rw
, int access_type
)
1397 qemu_log("%s\n", __func__
);
1399 if ((access_type
== ACCESS_CODE
&& msr_ir
== 0) ||
1400 (access_type
!= ACCESS_CODE
&& msr_dr
== 0)) {
1401 if (env
->mmu_model
== POWERPC_MMU_BOOKE
) {
1402 /* The BookE MMU always performs address translation. The
1403 IS and DS bits only affect the address space. */
1404 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1406 } else if (env
->mmu_model
== POWERPC_MMU_BOOKE206
) {
1407 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1410 /* No address translation. */
1411 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1415 switch (env
->mmu_model
) {
1416 case POWERPC_MMU_32B
:
1417 case POWERPC_MMU_601
:
1418 case POWERPC_MMU_SOFT_6xx
:
1419 case POWERPC_MMU_SOFT_74xx
:
1420 /* Try to find a BAT */
1421 if (env
->nb_BATs
!= 0) {
1422 ret
= get_bat(env
, ctx
, eaddr
, rw
, access_type
);
1424 #if defined(TARGET_PPC64)
1425 case POWERPC_MMU_64B
:
1426 case POWERPC_MMU_2_06
:
1427 case POWERPC_MMU_2_06d
:
1430 /* We didn't match any BAT entry or don't have BATs */
1431 ret
= get_segment(env
, ctx
, eaddr
, rw
, access_type
);
1434 case POWERPC_MMU_SOFT_4xx
:
1435 case POWERPC_MMU_SOFT_4xx_Z
:
1436 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1439 case POWERPC_MMU_BOOKE
:
1440 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1443 case POWERPC_MMU_BOOKE206
:
1444 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1447 case POWERPC_MMU_MPC8xx
:
1449 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1451 case POWERPC_MMU_REAL
:
1452 cpu_abort(env
, "PowerPC in real mode do not do any translation\n");
1455 cpu_abort(env
, "Unknown or invalid MMU model\n");
1460 qemu_log("%s address " TARGET_FMT_lx
" => %d " TARGET_FMT_plx
"\n",
1461 __func__
, eaddr
, ret
, ctx
->raddr
);
1467 hwaddr
cpu_get_phys_page_debug(CPUPPCState
*env
, target_ulong addr
)
1471 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0)) {
1475 return ctx
.raddr
& TARGET_PAGE_MASK
;
1478 static void booke206_update_mas_tlb_miss(CPUPPCState
*env
, target_ulong address
,
1481 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
1482 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
1483 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
1484 env
->spr
[SPR_BOOKE_MAS3
] = 0;
1485 env
->spr
[SPR_BOOKE_MAS6
] = 0;
1486 env
->spr
[SPR_BOOKE_MAS7
] = 0;
1489 if (((rw
== 2) && msr_ir
) || ((rw
!= 2) && msr_dr
)) {
1490 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
1491 env
->spr
[SPR_BOOKE_MAS6
] |= MAS6_SAS
;
1494 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_VALID
;
1495 env
->spr
[SPR_BOOKE_MAS2
] |= address
& MAS2_EPN_MASK
;
1497 switch (env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TIDSELD_PIDZ
) {
1498 case MAS4_TIDSELD_PID0
:
1499 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID
] << MAS1_TID_SHIFT
;
1501 case MAS4_TIDSELD_PID1
:
1502 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID1
] << MAS1_TID_SHIFT
;
1504 case MAS4_TIDSELD_PID2
:
1505 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID2
] << MAS1_TID_SHIFT
;
1509 env
->spr
[SPR_BOOKE_MAS6
] |= env
->spr
[SPR_BOOKE_PID
] << 16;
1511 /* next victim logic */
1512 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
1514 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
1515 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
1518 /* Perform address translation */
1519 int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
, int rw
,
1529 access_type
= ACCESS_CODE
;
1532 access_type
= env
->access_type
;
1534 ret
= get_physical_address(env
, &ctx
, address
, rw
, access_type
);
1536 tlb_set_page(env
, address
& TARGET_PAGE_MASK
,
1537 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1538 mmu_idx
, TARGET_PAGE_SIZE
);
1540 } else if (ret
< 0) {
1542 if (access_type
== ACCESS_CODE
) {
1545 /* No matches in page tables or TLB */
1546 switch (env
->mmu_model
) {
1547 case POWERPC_MMU_SOFT_6xx
:
1548 env
->exception_index
= POWERPC_EXCP_IFTLB
;
1549 env
->error_code
= 1 << 18;
1550 env
->spr
[SPR_IMISS
] = address
;
1551 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1553 case POWERPC_MMU_SOFT_74xx
:
1554 env
->exception_index
= POWERPC_EXCP_IFTLB
;
1556 case POWERPC_MMU_SOFT_4xx
:
1557 case POWERPC_MMU_SOFT_4xx_Z
:
1558 env
->exception_index
= POWERPC_EXCP_ITLB
;
1559 env
->error_code
= 0;
1560 env
->spr
[SPR_40x_DEAR
] = address
;
1561 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1563 case POWERPC_MMU_32B
:
1564 case POWERPC_MMU_601
:
1565 #if defined(TARGET_PPC64)
1566 case POWERPC_MMU_64B
:
1567 case POWERPC_MMU_2_06
:
1568 case POWERPC_MMU_2_06d
:
1570 env
->exception_index
= POWERPC_EXCP_ISI
;
1571 env
->error_code
= 0x40000000;
1573 case POWERPC_MMU_BOOKE206
:
1574 booke206_update_mas_tlb_miss(env
, address
, rw
);
1576 case POWERPC_MMU_BOOKE
:
1577 env
->exception_index
= POWERPC_EXCP_ITLB
;
1578 env
->error_code
= 0;
1579 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1581 case POWERPC_MMU_MPC8xx
:
1583 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1585 case POWERPC_MMU_REAL
:
1586 cpu_abort(env
, "PowerPC in real mode should never raise "
1587 "any MMU exceptions\n");
1590 cpu_abort(env
, "Unknown or invalid MMU model\n");
1595 /* Access rights violation */
1596 env
->exception_index
= POWERPC_EXCP_ISI
;
1597 env
->error_code
= 0x08000000;
1600 /* No execute protection violation */
1601 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1602 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1603 env
->spr
[SPR_BOOKE_ESR
] = 0x00000000;
1605 env
->exception_index
= POWERPC_EXCP_ISI
;
1606 env
->error_code
= 0x10000000;
1609 /* Direct store exception */
1610 /* No code fetch is allowed in direct-store areas */
1611 env
->exception_index
= POWERPC_EXCP_ISI
;
1612 env
->error_code
= 0x10000000;
1614 #if defined(TARGET_PPC64)
1616 /* No match in segment table */
1617 env
->exception_index
= POWERPC_EXCP_ISEG
;
1618 env
->error_code
= 0;
1625 /* No matches in page tables or TLB */
1626 switch (env
->mmu_model
) {
1627 case POWERPC_MMU_SOFT_6xx
:
1629 env
->exception_index
= POWERPC_EXCP_DSTLB
;
1630 env
->error_code
= 1 << 16;
1632 env
->exception_index
= POWERPC_EXCP_DLTLB
;
1633 env
->error_code
= 0;
1635 env
->spr
[SPR_DMISS
] = address
;
1636 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1638 env
->error_code
|= ctx
.key
<< 19;
1639 env
->spr
[SPR_HASH1
] = env
->htab_base
+
1640 get_pteg_offset(env
, ctx
.hash
[0], HASH_PTE_SIZE_32
);
1641 env
->spr
[SPR_HASH2
] = env
->htab_base
+
1642 get_pteg_offset(env
, ctx
.hash
[1], HASH_PTE_SIZE_32
);
1644 case POWERPC_MMU_SOFT_74xx
:
1646 env
->exception_index
= POWERPC_EXCP_DSTLB
;
1648 env
->exception_index
= POWERPC_EXCP_DLTLB
;
1651 /* Implement LRU algorithm */
1652 env
->error_code
= ctx
.key
<< 19;
1653 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1654 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1655 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1657 case POWERPC_MMU_SOFT_4xx
:
1658 case POWERPC_MMU_SOFT_4xx_Z
:
1659 env
->exception_index
= POWERPC_EXCP_DTLB
;
1660 env
->error_code
= 0;
1661 env
->spr
[SPR_40x_DEAR
] = address
;
1663 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1665 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1668 case POWERPC_MMU_32B
:
1669 case POWERPC_MMU_601
:
1670 #if defined(TARGET_PPC64)
1671 case POWERPC_MMU_64B
:
1672 case POWERPC_MMU_2_06
:
1673 case POWERPC_MMU_2_06d
:
1675 env
->exception_index
= POWERPC_EXCP_DSI
;
1676 env
->error_code
= 0;
1677 env
->spr
[SPR_DAR
] = address
;
1679 env
->spr
[SPR_DSISR
] = 0x42000000;
1681 env
->spr
[SPR_DSISR
] = 0x40000000;
1684 case POWERPC_MMU_MPC8xx
:
1686 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1688 case POWERPC_MMU_BOOKE206
:
1689 booke206_update_mas_tlb_miss(env
, address
, rw
);
1691 case POWERPC_MMU_BOOKE
:
1692 env
->exception_index
= POWERPC_EXCP_DTLB
;
1693 env
->error_code
= 0;
1694 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1695 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1697 case POWERPC_MMU_REAL
:
1698 cpu_abort(env
, "PowerPC in real mode should never raise "
1699 "any MMU exceptions\n");
1702 cpu_abort(env
, "Unknown or invalid MMU model\n");
1707 /* Access rights violation */
1708 env
->exception_index
= POWERPC_EXCP_DSI
;
1709 env
->error_code
= 0;
1710 if (env
->mmu_model
== POWERPC_MMU_SOFT_4xx
1711 || env
->mmu_model
== POWERPC_MMU_SOFT_4xx_Z
) {
1712 env
->spr
[SPR_40x_DEAR
] = address
;
1714 env
->spr
[SPR_40x_ESR
] |= 0x00800000;
1716 } else if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1717 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1718 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1719 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1721 env
->spr
[SPR_DAR
] = address
;
1723 env
->spr
[SPR_DSISR
] = 0x0A000000;
1725 env
->spr
[SPR_DSISR
] = 0x08000000;
1730 /* Direct store exception */
1731 switch (access_type
) {
1733 /* Floating point load/store */
1734 env
->exception_index
= POWERPC_EXCP_ALIGN
;
1735 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1736 env
->spr
[SPR_DAR
] = address
;
1739 /* lwarx, ldarx or stwcx. */
1740 env
->exception_index
= POWERPC_EXCP_DSI
;
1741 env
->error_code
= 0;
1742 env
->spr
[SPR_DAR
] = address
;
1744 env
->spr
[SPR_DSISR
] = 0x06000000;
1746 env
->spr
[SPR_DSISR
] = 0x04000000;
1750 /* eciwx or ecowx */
1751 env
->exception_index
= POWERPC_EXCP_DSI
;
1752 env
->error_code
= 0;
1753 env
->spr
[SPR_DAR
] = address
;
1755 env
->spr
[SPR_DSISR
] = 0x06100000;
1757 env
->spr
[SPR_DSISR
] = 0x04100000;
1761 printf("DSI: invalid exception (%d)\n", ret
);
1762 env
->exception_index
= POWERPC_EXCP_PROGRAM
;
1764 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1765 env
->spr
[SPR_DAR
] = address
;
1769 #if defined(TARGET_PPC64)
1771 /* No match in segment table */
1772 env
->exception_index
= POWERPC_EXCP_DSEG
;
1773 env
->error_code
= 0;
1774 env
->spr
[SPR_DAR
] = address
;
1780 printf("%s: set exception to %d %02x\n", __func__
,
1781 env
->exception
, env
->error_code
);
1789 /*****************************************************************************/
1790 /* BATs management */
1791 #if !defined(FLUSH_ALL_TLBS)
1792 static inline void do_invalidate_BAT(CPUPPCState
*env
, target_ulong BATu
,
1795 target_ulong base
, end
, page
;
1797 base
= BATu
& ~0x0001FFFF;
1798 end
= base
+ mask
+ 0x00020000;
1799 LOG_BATS("Flush BAT from " TARGET_FMT_lx
" to " TARGET_FMT_lx
" ("
1800 TARGET_FMT_lx
")\n", base
, end
, mask
);
1801 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
1802 tlb_flush_page(env
, page
);
1804 LOG_BATS("Flush done\n");
1808 static inline void dump_store_bat(CPUPPCState
*env
, char ID
, int ul
, int nr
,
1811 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx
" (" TARGET_FMT_lx
")\n", ID
,
1812 nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1815 void helper_store_ibatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1819 dump_store_bat(env
, 'I', 0, nr
, value
);
1820 if (env
->IBAT
[0][nr
] != value
) {
1821 mask
= (value
<< 15) & 0x0FFE0000UL
;
1822 #if !defined(FLUSH_ALL_TLBS)
1823 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1825 /* When storing valid upper BAT, mask BEPI and BRPN
1826 * and invalidate all TLBs covered by this BAT
1828 mask
= (value
<< 15) & 0x0FFE0000UL
;
1829 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1830 (value
& ~0x0001FFFFUL
& ~mask
);
1831 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1832 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1833 #if !defined(FLUSH_ALL_TLBS)
1834 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1841 void helper_store_ibatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1843 dump_store_bat(env
, 'I', 1, nr
, value
);
1844 env
->IBAT
[1][nr
] = value
;
1847 void helper_store_dbatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1851 dump_store_bat(env
, 'D', 0, nr
, value
);
1852 if (env
->DBAT
[0][nr
] != value
) {
1853 /* When storing valid upper BAT, mask BEPI and BRPN
1854 * and invalidate all TLBs covered by this BAT
1856 mask
= (value
<< 15) & 0x0FFE0000UL
;
1857 #if !defined(FLUSH_ALL_TLBS)
1858 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1860 mask
= (value
<< 15) & 0x0FFE0000UL
;
1861 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1862 (value
& ~0x0001FFFFUL
& ~mask
);
1863 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1864 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1865 #if !defined(FLUSH_ALL_TLBS)
1866 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1873 void helper_store_dbatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1875 dump_store_bat(env
, 'D', 1, nr
, value
);
1876 env
->DBAT
[1][nr
] = value
;
1879 void helper_store_601_batu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1882 #if defined(FLUSH_ALL_TLBS)
1886 dump_store_bat(env
, 'I', 0, nr
, value
);
1887 if (env
->IBAT
[0][nr
] != value
) {
1888 #if defined(FLUSH_ALL_TLBS)
1891 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1892 if (env
->IBAT
[1][nr
] & 0x40) {
1893 /* Invalidate BAT only if it is valid */
1894 #if !defined(FLUSH_ALL_TLBS)
1895 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1900 /* When storing valid upper BAT, mask BEPI and BRPN
1901 * and 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
);
1913 #if defined(FLUSH_ALL_TLBS)
1921 void helper_store_601_batl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1923 #if !defined(FLUSH_ALL_TLBS)
1929 dump_store_bat(env
, 'I', 1, nr
, value
);
1930 if (env
->IBAT
[1][nr
] != value
) {
1931 #if defined(FLUSH_ALL_TLBS)
1934 if (env
->IBAT
[1][nr
] & 0x40) {
1935 #if !defined(FLUSH_ALL_TLBS)
1936 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1937 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1943 #if !defined(FLUSH_ALL_TLBS)
1944 mask
= (value
<< 17) & 0x0FFE0000UL
;
1945 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1950 env
->IBAT
[1][nr
] = value
;
1951 env
->DBAT
[1][nr
] = value
;
1952 #if defined(FLUSH_ALL_TLBS)
1960 /*****************************************************************************/
1961 /* TLB management */
1962 void ppc_tlb_invalidate_all(CPUPPCState
*env
)
1964 switch (env
->mmu_model
) {
1965 case POWERPC_MMU_SOFT_6xx
:
1966 case POWERPC_MMU_SOFT_74xx
:
1967 ppc6xx_tlb_invalidate_all(env
);
1969 case POWERPC_MMU_SOFT_4xx
:
1970 case POWERPC_MMU_SOFT_4xx_Z
:
1971 ppc4xx_tlb_invalidate_all(env
);
1973 case POWERPC_MMU_REAL
:
1974 cpu_abort(env
, "No TLB for PowerPC 4xx in real mode\n");
1976 case POWERPC_MMU_MPC8xx
:
1978 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1980 case POWERPC_MMU_BOOKE
:
1983 case POWERPC_MMU_BOOKE206
:
1984 booke206_flush_tlb(env
, -1, 0);
1986 case POWERPC_MMU_32B
:
1987 case POWERPC_MMU_601
:
1988 #if defined(TARGET_PPC64)
1989 case POWERPC_MMU_64B
:
1990 case POWERPC_MMU_2_06
:
1991 case POWERPC_MMU_2_06d
:
1992 #endif /* defined(TARGET_PPC64) */
1997 cpu_abort(env
, "Unknown MMU model\n");
2002 void ppc_tlb_invalidate_one(CPUPPCState
*env
, target_ulong addr
)
2004 #if !defined(FLUSH_ALL_TLBS)
2005 addr
&= TARGET_PAGE_MASK
;
2006 switch (env
->mmu_model
) {
2007 case POWERPC_MMU_SOFT_6xx
:
2008 case POWERPC_MMU_SOFT_74xx
:
2009 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
2010 if (env
->id_tlbs
== 1) {
2011 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
2014 case POWERPC_MMU_SOFT_4xx
:
2015 case POWERPC_MMU_SOFT_4xx_Z
:
2016 ppc4xx_tlb_invalidate_virt(env
, addr
, env
->spr
[SPR_40x_PID
]);
2018 case POWERPC_MMU_REAL
:
2019 cpu_abort(env
, "No TLB for PowerPC 4xx in real mode\n");
2021 case POWERPC_MMU_MPC8xx
:
2023 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
2025 case POWERPC_MMU_BOOKE
:
2027 cpu_abort(env
, "BookE MMU model is not implemented\n");
2029 case POWERPC_MMU_BOOKE206
:
2031 cpu_abort(env
, "BookE 2.06 MMU model is not implemented\n");
2033 case POWERPC_MMU_32B
:
2034 case POWERPC_MMU_601
:
2035 /* tlbie invalidate TLBs for all segments */
2036 addr
&= ~((target_ulong
)-1ULL << 28);
2037 /* XXX: this case should be optimized,
2038 * giving a mask to tlb_flush_page
2040 tlb_flush_page(env
, addr
| (0x0 << 28));
2041 tlb_flush_page(env
, addr
| (0x1 << 28));
2042 tlb_flush_page(env
, addr
| (0x2 << 28));
2043 tlb_flush_page(env
, addr
| (0x3 << 28));
2044 tlb_flush_page(env
, addr
| (0x4 << 28));
2045 tlb_flush_page(env
, addr
| (0x5 << 28));
2046 tlb_flush_page(env
, addr
| (0x6 << 28));
2047 tlb_flush_page(env
, addr
| (0x7 << 28));
2048 tlb_flush_page(env
, addr
| (0x8 << 28));
2049 tlb_flush_page(env
, addr
| (0x9 << 28));
2050 tlb_flush_page(env
, addr
| (0xA << 28));
2051 tlb_flush_page(env
, addr
| (0xB << 28));
2052 tlb_flush_page(env
, addr
| (0xC << 28));
2053 tlb_flush_page(env
, addr
| (0xD << 28));
2054 tlb_flush_page(env
, addr
| (0xE << 28));
2055 tlb_flush_page(env
, addr
| (0xF << 28));
2057 #if defined(TARGET_PPC64)
2058 case POWERPC_MMU_64B
:
2059 case POWERPC_MMU_2_06
:
2060 case POWERPC_MMU_2_06d
:
2061 /* tlbie invalidate TLBs for all segments */
2062 /* XXX: given the fact that there are too many segments to invalidate,
2063 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
2064 * we just invalidate all TLBs
2068 #endif /* defined(TARGET_PPC64) */
2071 cpu_abort(env
, "Unknown MMU model\n");
2075 ppc_tlb_invalidate_all(env
);
2079 /*****************************************************************************/
2080 /* Special registers manipulation */
2081 void ppc_store_sdr1(CPUPPCState
*env
, target_ulong value
)
2083 LOG_MMU("%s: " TARGET_FMT_lx
"\n", __func__
, value
);
2084 if (env
->spr
[SPR_SDR1
] != value
) {
2085 env
->spr
[SPR_SDR1
] = value
;
2086 #if defined(TARGET_PPC64)
2087 if (env
->mmu_model
& POWERPC_MMU_64
) {
2088 target_ulong htabsize
= value
& SDR_64_HTABSIZE
;
2090 if (htabsize
> 28) {
2091 fprintf(stderr
, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2092 " stored in SDR1\n", htabsize
);
2095 env
->htab_mask
= (1ULL << (htabsize
+ 18)) - 1;
2096 env
->htab_base
= value
& SDR_64_HTABORG
;
2098 #endif /* defined(TARGET_PPC64) */
2100 /* FIXME: Should check for valid HTABMASK values */
2101 env
->htab_mask
= ((value
& SDR_32_HTABMASK
) << 16) | 0xFFFF;
2102 env
->htab_base
= value
& SDR_32_HTABORG
;
2108 /* Segment registers load and store */
2109 target_ulong
helper_load_sr(CPUPPCState
*env
, target_ulong sr_num
)
2111 #if defined(TARGET_PPC64)
2112 if (env
->mmu_model
& POWERPC_MMU_64
) {
2117 return env
->sr
[sr_num
];
2120 void helper_store_sr(CPUPPCState
*env
, target_ulong srnum
, target_ulong value
)
2122 LOG_MMU("%s: reg=%d " TARGET_FMT_lx
" " TARGET_FMT_lx
"\n", __func__
,
2123 (int)srnum
, value
, env
->sr
[srnum
]);
2124 #if defined(TARGET_PPC64)
2125 if (env
->mmu_model
& POWERPC_MMU_64
) {
2126 uint64_t rb
= 0, rs
= 0;
2129 rb
|= ((uint32_t)srnum
& 0xf) << 28;
2130 /* Set the valid bit */
2133 rb
|= (uint32_t)srnum
;
2136 rs
|= (value
& 0xfffffff) << 12;
2138 rs
|= ((value
>> 27) & 0xf) << 8;
2140 ppc_store_slb(env
, rb
, rs
);
2143 if (env
->sr
[srnum
] != value
) {
2144 env
->sr
[srnum
] = value
;
2145 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2146 flusing the whole TLB. */
2147 #if !defined(FLUSH_ALL_TLBS) && 0
2149 target_ulong page
, end
;
2150 /* Invalidate 256 MB of virtual memory */
2151 page
= (16 << 20) * srnum
;
2152 end
= page
+ (16 << 20);
2153 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
2154 tlb_flush_page(env
, page
);
2162 #endif /* !defined(CONFIG_USER_ONLY) */
2164 #if !defined(CONFIG_USER_ONLY)
2165 /* TLB management */
2166 void helper_tlbia(CPUPPCState
*env
)
2168 ppc_tlb_invalidate_all(env
);
2171 void helper_tlbie(CPUPPCState
*env
, target_ulong addr
)
2173 ppc_tlb_invalidate_one(env
, addr
);
2176 /* Software driven TLBs management */
2177 /* PowerPC 602/603 software TLB load instructions helpers */
2178 static void do_6xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2180 target_ulong RPN
, CMP
, EPN
;
2183 RPN
= env
->spr
[SPR_RPA
];
2185 CMP
= env
->spr
[SPR_ICMP
];
2186 EPN
= env
->spr
[SPR_IMISS
];
2188 CMP
= env
->spr
[SPR_DCMP
];
2189 EPN
= env
->spr
[SPR_DMISS
];
2191 way
= (env
->spr
[SPR_SRR1
] >> 17) & 1;
2192 (void)EPN
; /* avoid a compiler warning */
2193 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2194 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2196 /* Store this TLB */
2197 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2198 way
, is_code
, CMP
, RPN
);
2201 void helper_6xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2203 do_6xx_tlb(env
, EPN
, 0);
2206 void helper_6xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2208 do_6xx_tlb(env
, EPN
, 1);
2211 /* PowerPC 74xx software TLB load instructions helpers */
2212 static void do_74xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2214 target_ulong RPN
, CMP
, EPN
;
2217 RPN
= env
->spr
[SPR_PTELO
];
2218 CMP
= env
->spr
[SPR_PTEHI
];
2219 EPN
= env
->spr
[SPR_TLBMISS
] & ~0x3;
2220 way
= env
->spr
[SPR_TLBMISS
] & 0x3;
2221 (void)EPN
; /* avoid a compiler warning */
2222 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2223 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2225 /* Store this TLB */
2226 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2227 way
, is_code
, CMP
, RPN
);
2230 void helper_74xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2232 do_74xx_tlb(env
, EPN
, 0);
2235 void helper_74xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2237 do_74xx_tlb(env
, EPN
, 1);
2240 /*****************************************************************************/
2241 /* PowerPC 601 specific instructions (POWER bridge) */
2243 target_ulong
helper_rac(CPUPPCState
*env
, target_ulong addr
)
2247 target_ulong ret
= 0;
2249 /* We don't have to generate many instances of this instruction,
2250 * as rac is supervisor only.
2252 /* XXX: FIX THIS: Pretend we have no BAT */
2253 nb_BATs
= env
->nb_BATs
;
2255 if (get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) == 0) {
2258 env
->nb_BATs
= nb_BATs
;
2262 static inline target_ulong
booke_tlb_to_page_size(int size
)
2264 return 1024 << (2 * size
);
2267 static inline int booke_page_size_to_tlb(target_ulong page_size
)
2271 switch (page_size
) {
2305 #if defined(TARGET_PPC64)
2306 case 0x000100000000ULL
:
2309 case 0x000400000000ULL
:
2312 case 0x001000000000ULL
:
2315 case 0x004000000000ULL
:
2318 case 0x010000000000ULL
:
2330 /* Helpers for 4xx TLB management */
2331 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2333 #define PPC4XX_TLBHI_V 0x00000040
2334 #define PPC4XX_TLBHI_E 0x00000020
2335 #define PPC4XX_TLBHI_SIZE_MIN 0
2336 #define PPC4XX_TLBHI_SIZE_MAX 7
2337 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2338 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2339 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2341 #define PPC4XX_TLBLO_EX 0x00000200
2342 #define PPC4XX_TLBLO_WR 0x00000100
2343 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2344 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2346 target_ulong
helper_4xx_tlbre_hi(CPUPPCState
*env
, target_ulong entry
)
2352 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2353 tlb
= &env
->tlb
.tlbe
[entry
];
2355 if (tlb
->prot
& PAGE_VALID
) {
2356 ret
|= PPC4XX_TLBHI_V
;
2358 size
= booke_page_size_to_tlb(tlb
->size
);
2359 if (size
< PPC4XX_TLBHI_SIZE_MIN
|| size
> PPC4XX_TLBHI_SIZE_MAX
) {
2360 size
= PPC4XX_TLBHI_SIZE_DEFAULT
;
2362 ret
|= size
<< PPC4XX_TLBHI_SIZE_SHIFT
;
2363 env
->spr
[SPR_40x_PID
] = tlb
->PID
;
2367 target_ulong
helper_4xx_tlbre_lo(CPUPPCState
*env
, target_ulong entry
)
2372 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2373 tlb
= &env
->tlb
.tlbe
[entry
];
2375 if (tlb
->prot
& PAGE_EXEC
) {
2376 ret
|= PPC4XX_TLBLO_EX
;
2378 if (tlb
->prot
& PAGE_WRITE
) {
2379 ret
|= PPC4XX_TLBLO_WR
;
2384 void helper_4xx_tlbwe_hi(CPUPPCState
*env
, target_ulong entry
,
2388 target_ulong page
, end
;
2390 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2392 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2393 tlb
= &env
->tlb
.tlbe
[entry
];
2394 /* Invalidate previous TLB (if it's valid) */
2395 if (tlb
->prot
& PAGE_VALID
) {
2396 end
= tlb
->EPN
+ tlb
->size
;
2397 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx
" end "
2398 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2399 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2400 tlb_flush_page(env
, page
);
2403 tlb
->size
= booke_tlb_to_page_size((val
>> PPC4XX_TLBHI_SIZE_SHIFT
)
2404 & PPC4XX_TLBHI_SIZE_MASK
);
2405 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2406 * If this ever occurs, one should use the ppcemb target instead
2407 * of the ppc or ppc64 one
2409 if ((val
& PPC4XX_TLBHI_V
) && tlb
->size
< TARGET_PAGE_SIZE
) {
2410 cpu_abort(env
, "TLB size " TARGET_FMT_lu
" < %u "
2411 "are not supported (%d)\n",
2412 tlb
->size
, TARGET_PAGE_SIZE
, (int)((val
>> 7) & 0x7));
2414 tlb
->EPN
= val
& ~(tlb
->size
- 1);
2415 if (val
& PPC4XX_TLBHI_V
) {
2416 tlb
->prot
|= PAGE_VALID
;
2417 if (val
& PPC4XX_TLBHI_E
) {
2418 /* XXX: TO BE FIXED */
2420 "Little-endian TLB entries are not supported by now\n");
2423 tlb
->prot
&= ~PAGE_VALID
;
2425 tlb
->PID
= env
->spr
[SPR_40x_PID
]; /* PID */
2426 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2427 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2428 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2429 tlb
->prot
& PAGE_READ
? 'r' : '-',
2430 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2431 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2432 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2433 /* Invalidate new TLB (if valid) */
2434 if (tlb
->prot
& PAGE_VALID
) {
2435 end
= tlb
->EPN
+ tlb
->size
;
2436 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx
" end "
2437 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2438 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2439 tlb_flush_page(env
, page
);
2444 void helper_4xx_tlbwe_lo(CPUPPCState
*env
, target_ulong entry
,
2449 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2451 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2452 tlb
= &env
->tlb
.tlbe
[entry
];
2453 tlb
->attr
= val
& PPC4XX_TLBLO_ATTR_MASK
;
2454 tlb
->RPN
= val
& PPC4XX_TLBLO_RPN_MASK
;
2455 tlb
->prot
= PAGE_READ
;
2456 if (val
& PPC4XX_TLBLO_EX
) {
2457 tlb
->prot
|= PAGE_EXEC
;
2459 if (val
& PPC4XX_TLBLO_WR
) {
2460 tlb
->prot
|= PAGE_WRITE
;
2462 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2463 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2464 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2465 tlb
->prot
& PAGE_READ
? 'r' : '-',
2466 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2467 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2468 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2471 target_ulong
helper_4xx_tlbsx(CPUPPCState
*env
, target_ulong address
)
2473 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_40x_PID
]);
2476 /* PowerPC 440 TLB management */
2477 void helper_440_tlbwe(CPUPPCState
*env
, uint32_t word
, target_ulong entry
,
2481 target_ulong EPN
, RPN
, size
;
2484 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx
"\n",
2485 __func__
, word
, (int)entry
, value
);
2488 tlb
= &env
->tlb
.tlbe
[entry
];
2491 /* Just here to please gcc */
2493 EPN
= value
& 0xFFFFFC00;
2494 if ((tlb
->prot
& PAGE_VALID
) && EPN
!= tlb
->EPN
) {
2498 size
= booke_tlb_to_page_size((value
>> 4) & 0xF);
2499 if ((tlb
->prot
& PAGE_VALID
) && tlb
->size
< size
) {
2504 tlb
->attr
|= (value
>> 8) & 1;
2505 if (value
& 0x200) {
2506 tlb
->prot
|= PAGE_VALID
;
2508 if (tlb
->prot
& PAGE_VALID
) {
2509 tlb
->prot
&= ~PAGE_VALID
;
2513 tlb
->PID
= env
->spr
[SPR_440_MMUCR
] & 0x000000FF;
2514 if (do_flush_tlbs
) {
2519 RPN
= value
& 0xFFFFFC0F;
2520 if ((tlb
->prot
& PAGE_VALID
) && tlb
->RPN
!= RPN
) {
2526 tlb
->attr
= (tlb
->attr
& 0x1) | (value
& 0x0000FF00);
2527 tlb
->prot
= tlb
->prot
& PAGE_VALID
;
2529 tlb
->prot
|= PAGE_READ
<< 4;
2532 tlb
->prot
|= PAGE_WRITE
<< 4;
2535 tlb
->prot
|= PAGE_EXEC
<< 4;
2538 tlb
->prot
|= PAGE_READ
;
2541 tlb
->prot
|= PAGE_WRITE
;
2544 tlb
->prot
|= PAGE_EXEC
;
2550 target_ulong
helper_440_tlbre(CPUPPCState
*env
, uint32_t word
,
2558 tlb
= &env
->tlb
.tlbe
[entry
];
2561 /* Just here to please gcc */
2564 size
= booke_page_size_to_tlb(tlb
->size
);
2565 if (size
< 0 || size
> 0xF) {
2569 if (tlb
->attr
& 0x1) {
2572 if (tlb
->prot
& PAGE_VALID
) {
2575 env
->spr
[SPR_440_MMUCR
] &= ~0x000000FF;
2576 env
->spr
[SPR_440_MMUCR
] |= tlb
->PID
;
2582 ret
= tlb
->attr
& ~0x1;
2583 if (tlb
->prot
& (PAGE_READ
<< 4)) {
2586 if (tlb
->prot
& (PAGE_WRITE
<< 4)) {
2589 if (tlb
->prot
& (PAGE_EXEC
<< 4)) {
2592 if (tlb
->prot
& PAGE_READ
) {
2595 if (tlb
->prot
& PAGE_WRITE
) {
2598 if (tlb
->prot
& PAGE_EXEC
) {
2606 target_ulong
helper_440_tlbsx(CPUPPCState
*env
, target_ulong address
)
2608 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_440_MMUCR
] & 0xFF);
2611 /* PowerPC BookE 2.06 TLB management */
2613 static ppcmas_tlb_t
*booke206_cur_tlb(CPUPPCState
*env
)
2615 uint32_t tlbncfg
= 0;
2616 int esel
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ESEL_MASK
) >> MAS0_ESEL_SHIFT
;
2617 int ea
= (env
->spr
[SPR_BOOKE_MAS2
] & MAS2_EPN_MASK
);
2620 tlb
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2621 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlb
];
2623 if ((tlbncfg
& TLBnCFG_HES
) && (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_HES
)) {
2624 cpu_abort(env
, "we don't support HES yet\n");
2627 return booke206_get_tlbm(env
, tlb
, ea
, esel
);
2630 void helper_booke_setpid(CPUPPCState
*env
, uint32_t pidn
, target_ulong pid
)
2632 env
->spr
[pidn
] = pid
;
2633 /* changing PIDs mean we're in a different address space now */
2637 void helper_booke206_tlbwe(CPUPPCState
*env
)
2639 uint32_t tlbncfg
, tlbn
;
2641 uint32_t size_tlb
, size_ps
;
2645 switch (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_WQ_MASK
) {
2646 case MAS0_WQ_ALWAYS
:
2647 /* good to go, write that entry */
2650 /* XXX check if reserved */
2655 case MAS0_WQ_CLR_RSRV
:
2656 /* XXX clear entry */
2659 /* no idea what to do */
2663 if (((env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ATSEL
) == MAS0_ATSEL_LRAT
) &&
2665 /* XXX we don't support direct LRAT setting yet */
2666 fprintf(stderr
, "cpu: don't support LRAT setting yet\n");
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
);
2676 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2677 POWERPC_EXCP_INVAL
|
2678 POWERPC_EXCP_INVAL_INVAL
);
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 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2687 POWERPC_EXCP_INVAL
|
2688 POWERPC_EXCP_INVAL_INVAL
);
2692 cpu_abort(env
, "missing HV implementation\n");
2694 tlb
->mas7_3
= ((uint64_t)env
->spr
[SPR_BOOKE_MAS7
] << 32) |
2695 env
->spr
[SPR_BOOKE_MAS3
];
2696 tlb
->mas1
= env
->spr
[SPR_BOOKE_MAS1
];
2699 if (!(tlbncfg
& TLBnCFG_AVAIL
)) {
2700 /* force !AVAIL TLB entries to correct page size */
2701 tlb
->mas1
&= ~MAS1_TSIZE_MASK
;
2702 /* XXX can be configured in MMUCSR0 */
2703 tlb
->mas1
|= (tlbncfg
& TLBnCFG_MINSIZE
) >> 12;
2706 /* Make a mask from TLB size to discard invalid bits in EPN field */
2707 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2708 /* Add a mask for page attributes */
2709 mask
|= MAS2_ACM
| MAS2_VLE
| MAS2_W
| MAS2_I
| MAS2_M
| MAS2_G
| MAS2_E
;
2712 /* Executing a tlbwe instruction in 32-bit mode will set
2713 * bits 0:31 of the TLB EPN field to zero.
2718 tlb
->mas2
= env
->spr
[SPR_BOOKE_MAS2
] & mask
;
2720 if (!(tlbncfg
& TLBnCFG_IPROT
)) {
2721 /* no IPROT supported by TLB */
2722 tlb
->mas1
&= ~MAS1_IPROT
;
2725 if (booke206_tlb_to_page_size(env
, tlb
) == TARGET_PAGE_SIZE
) {
2726 tlb_flush_page(env
, tlb
->mas2
& MAS2_EPN_MASK
);
2732 static inline void booke206_tlb_to_mas(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2734 int tlbn
= booke206_tlbm_to_tlbn(env
, tlb
);
2735 int way
= booke206_tlbm_to_way(env
, tlb
);
2737 env
->spr
[SPR_BOOKE_MAS0
] = tlbn
<< MAS0_TLBSEL_SHIFT
;
2738 env
->spr
[SPR_BOOKE_MAS0
] |= way
<< MAS0_ESEL_SHIFT
;
2739 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2741 env
->spr
[SPR_BOOKE_MAS1
] = tlb
->mas1
;
2742 env
->spr
[SPR_BOOKE_MAS2
] = tlb
->mas2
;
2743 env
->spr
[SPR_BOOKE_MAS3
] = tlb
->mas7_3
;
2744 env
->spr
[SPR_BOOKE_MAS7
] = tlb
->mas7_3
>> 32;
2747 void helper_booke206_tlbre(CPUPPCState
*env
)
2749 ppcmas_tlb_t
*tlb
= NULL
;
2751 tlb
= booke206_cur_tlb(env
);
2753 env
->spr
[SPR_BOOKE_MAS1
] = 0;
2755 booke206_tlb_to_mas(env
, tlb
);
2759 void helper_booke206_tlbsx(CPUPPCState
*env
, target_ulong address
)
2761 ppcmas_tlb_t
*tlb
= NULL
;
2766 spid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID_MASK
) >> MAS6_SPID_SHIFT
;
2767 sas
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
;
2769 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2770 int ways
= booke206_tlb_ways(env
, i
);
2772 for (j
= 0; j
< ways
; j
++) {
2773 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2779 if (ppcmas_tlb_check(env
, tlb
, &raddr
, address
, spid
)) {
2783 if (sas
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
2787 booke206_tlb_to_mas(env
, tlb
);
2792 /* no entry found, fill with defaults */
2793 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
2794 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
2795 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
2796 env
->spr
[SPR_BOOKE_MAS3
] = 0;
2797 env
->spr
[SPR_BOOKE_MAS7
] = 0;
2799 if (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
) {
2800 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
2803 env
->spr
[SPR_BOOKE_MAS1
] |= (env
->spr
[SPR_BOOKE_MAS6
] >> 16)
2806 /* next victim logic */
2807 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
2809 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
2810 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2813 static inline void booke206_invalidate_ea_tlb(CPUPPCState
*env
, int tlbn
,
2817 int ways
= booke206_tlb_ways(env
, tlbn
);
2820 for (i
= 0; i
< ways
; i
++) {
2821 ppcmas_tlb_t
*tlb
= booke206_get_tlbm(env
, tlbn
, ea
, i
);
2825 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2826 if (((tlb
->mas2
& MAS2_EPN_MASK
) == (ea
& mask
)) &&
2827 !(tlb
->mas1
& MAS1_IPROT
)) {
2828 tlb
->mas1
&= ~MAS1_VALID
;
2833 void helper_booke206_tlbivax(CPUPPCState
*env
, target_ulong address
)
2835 if (address
& 0x4) {
2836 /* flush all entries */
2837 if (address
& 0x8) {
2838 /* flush all of TLB1 */
2839 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB1
, 1);
2841 /* flush all of TLB0 */
2842 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB0
, 0);
2847 if (address
& 0x8) {
2848 /* flush TLB1 entries */
2849 booke206_invalidate_ea_tlb(env
, 1, address
);
2852 /* flush TLB0 entries */
2853 booke206_invalidate_ea_tlb(env
, 0, address
);
2854 tlb_flush_page(env
, address
& MAS2_EPN_MASK
);
2858 void helper_booke206_tlbilx0(CPUPPCState
*env
, target_ulong address
)
2860 /* XXX missing LPID handling */
2861 booke206_flush_tlb(env
, -1, 1);
2864 void helper_booke206_tlbilx1(CPUPPCState
*env
, target_ulong address
)
2867 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2868 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
2871 /* XXX missing LPID handling */
2872 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2873 tlb_size
= booke206_tlb_size(env
, i
);
2874 for (j
= 0; j
< tlb_size
; j
++) {
2875 if (!(tlb
[j
].mas1
& MAS1_IPROT
) &&
2876 ((tlb
[j
].mas1
& MAS1_TID_MASK
) == tid
)) {
2877 tlb
[j
].mas1
&= ~MAS1_VALID
;
2880 tlb
+= booke206_tlb_size(env
, i
);
2885 void helper_booke206_tlbilx3(CPUPPCState
*env
, target_ulong address
)
2889 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2890 int pid
= tid
>> MAS6_SPID_SHIFT
;
2891 int sgs
= env
->spr
[SPR_BOOKE_MAS5
] & MAS5_SGS
;
2892 int ind
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SIND
) ? MAS1_IND
: 0;
2893 /* XXX check for unsupported isize and raise an invalid opcode then */
2894 int size
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_ISIZE_MASK
;
2895 /* XXX implement MAV2 handling */
2898 /* XXX missing LPID handling */
2899 /* flush by pid and ea */
2900 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2901 int ways
= booke206_tlb_ways(env
, i
);
2903 for (j
= 0; j
< ways
; j
++) {
2904 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2908 if ((ppcmas_tlb_check(env
, tlb
, NULL
, address
, pid
) != 0) ||
2909 (tlb
->mas1
& MAS1_IPROT
) ||
2910 ((tlb
->mas1
& MAS1_IND
) != ind
) ||
2911 ((tlb
->mas8
& MAS8_TGS
) != sgs
)) {
2914 if (mav2
&& ((tlb
->mas1
& MAS1_TSIZE_MASK
) != size
)) {
2915 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2918 /* XXX e500mc doesn't match SAS, but other cores might */
2919 tlb
->mas1
&= ~MAS1_VALID
;
2925 void helper_booke206_tlbflush(CPUPPCState
*env
, uint32_t type
)
2930 flags
|= BOOKE206_FLUSH_TLB1
;
2934 flags
|= BOOKE206_FLUSH_TLB0
;
2937 booke206_flush_tlb(env
, flags
, 1);