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(cpu) log_cpu_state((cpu), 0)
37 # define LOG_MMU(...) do { } while (0)
38 # define LOG_MMU_STATE(cpu) 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 */
56 /* Context used internally during MMU translations */
57 typedef struct mmu_ctx_t mmu_ctx_t
;
59 hwaddr raddr
; /* Real address */
60 hwaddr eaddr
; /* Effective address */
61 int prot
; /* Protection bits */
62 hwaddr hash
[2]; /* Pagetable hash values */
63 target_ulong ptem
; /* Virtual segment ID | API */
64 int key
; /* Access key */
65 int nx
; /* Non-execute area */
68 /* Common routines used by software and hardware TLBs emulation */
69 static inline int pte_is_valid(target_ulong pte0
)
71 return pte0
& 0x80000000 ? 1 : 0;
74 static inline void pte_invalidate(target_ulong
*pte0
)
79 #define PTE_PTEM_MASK 0x7FFFFFBF
80 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
82 static int pp_check(int key
, int pp
, int nx
)
86 /* Compute access rights */
109 access
= PAGE_READ
| PAGE_WRITE
;
120 static int check_prot(int prot
, int rw
, int access_type
)
124 if (access_type
== ACCESS_CODE
) {
125 if (prot
& PAGE_EXEC
) {
131 if (prot
& PAGE_WRITE
) {
137 if (prot
& PAGE_READ
) {
147 static inline int ppc6xx_tlb_pte_check(mmu_ctx_t
*ctx
, target_ulong pte0
,
148 target_ulong pte1
, int h
, int rw
, int type
)
150 target_ulong ptem
, mmask
;
151 int access
, ret
, pteh
, ptev
, pp
;
154 /* Check validity and table match */
155 ptev
= pte_is_valid(pte0
);
156 pteh
= (pte0
>> 6) & 1;
157 if (ptev
&& h
== pteh
) {
158 /* Check vsid & api */
159 ptem
= pte0
& PTE_PTEM_MASK
;
160 mmask
= PTE_CHECK_MASK
;
161 pp
= pte1
& 0x00000003;
162 if (ptem
== ctx
->ptem
) {
163 if (ctx
->raddr
!= (hwaddr
)-1ULL) {
164 /* all matches should have equal RPN, WIMG & PP */
165 if ((ctx
->raddr
& mmask
) != (pte1
& mmask
)) {
166 qemu_log("Bad RPN/WIMG/PP\n");
170 /* Compute access rights */
171 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
172 /* Keep the matching PTE informations */
175 ret
= check_prot(ctx
->prot
, rw
, type
);
178 LOG_MMU("PTE access granted !\n");
180 /* Access right violation */
181 LOG_MMU("PTE access rejected\n");
189 static int pte_update_flags(mmu_ctx_t
*ctx
, target_ulong
*pte1p
,
194 /* Update page flags */
195 if (!(*pte1p
& 0x00000100)) {
196 /* Update accessed flag */
197 *pte1p
|= 0x00000100;
200 if (!(*pte1p
& 0x00000080)) {
201 if (rw
== 1 && ret
== 0) {
202 /* Update changed flag */
203 *pte1p
|= 0x00000080;
206 /* Force page fault for first write access */
207 ctx
->prot
&= ~PAGE_WRITE
;
214 /* Software driven TLB helpers */
215 static inline int ppc6xx_tlb_getnum(CPUPPCState
*env
, target_ulong eaddr
,
216 int way
, int is_code
)
220 /* Select TLB num in a way from address */
221 nr
= (eaddr
>> TARGET_PAGE_BITS
) & (env
->tlb_per_way
- 1);
223 nr
+= env
->tlb_per_way
* way
;
224 /* 6xx have separate TLBs for instructions and data */
225 if (is_code
&& env
->id_tlbs
== 1) {
232 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState
*env
)
237 /* LOG_SWTLB("Invalidate all TLBs\n"); */
238 /* Invalidate all defined software TLB */
240 if (env
->id_tlbs
== 1) {
243 for (nr
= 0; nr
< max
; nr
++) {
244 tlb
= &env
->tlb
.tlb6
[nr
];
245 pte_invalidate(&tlb
->pte0
);
250 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState
*env
,
252 int is_code
, int match_epn
)
254 #if !defined(FLUSH_ALL_TLBS)
258 /* Invalidate ITLB + DTLB, all ways */
259 for (way
= 0; way
< env
->nb_ways
; way
++) {
260 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
, is_code
);
261 tlb
= &env
->tlb
.tlb6
[nr
];
262 if (pte_is_valid(tlb
->pte0
) && (match_epn
== 0 || eaddr
== tlb
->EPN
)) {
263 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx
"\n", nr
,
265 pte_invalidate(&tlb
->pte0
);
266 tlb_flush_page(env
, tlb
->EPN
);
270 /* XXX: PowerPC specification say this is valid as well */
271 ppc6xx_tlb_invalidate_all(env
);
275 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState
*env
,
276 target_ulong eaddr
, int is_code
)
278 ppc6xx_tlb_invalidate_virt2(env
, eaddr
, is_code
, 0);
281 static void ppc6xx_tlb_store(CPUPPCState
*env
, target_ulong EPN
, int way
,
282 int is_code
, target_ulong pte0
, target_ulong pte1
)
287 nr
= ppc6xx_tlb_getnum(env
, EPN
, way
, is_code
);
288 tlb
= &env
->tlb
.tlb6
[nr
];
289 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
290 " PTE1 " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
, EPN
, pte0
, pte1
);
291 /* Invalidate any pending reference in QEMU for this virtual address */
292 ppc6xx_tlb_invalidate_virt2(env
, EPN
, is_code
, 1);
296 /* Store last way for LRU mechanism */
300 static inline int ppc6xx_tlb_check(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
301 target_ulong eaddr
, int rw
, int access_type
)
308 ret
= -1; /* No TLB found */
309 for (way
= 0; way
< env
->nb_ways
; way
++) {
310 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
,
311 access_type
== ACCESS_CODE
? 1 : 0);
312 tlb
= &env
->tlb
.tlb6
[nr
];
313 /* This test "emulates" the PTE index match for hardware TLBs */
314 if ((eaddr
& TARGET_PAGE_MASK
) != tlb
->EPN
) {
315 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx
" " TARGET_FMT_lx
316 "] <> " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
,
317 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
318 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
, eaddr
);
321 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx
" <> " TARGET_FMT_lx
" "
322 TARGET_FMT_lx
" %c %c\n", nr
, env
->nb_tlb
,
323 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
324 tlb
->EPN
, eaddr
, tlb
->pte1
,
325 rw
? 'S' : 'L', access_type
== ACCESS_CODE
? 'I' : 'D');
326 switch (ppc6xx_tlb_pte_check(ctx
, tlb
->pte0
, tlb
->pte1
, 0, rw
, access_type
)) {
328 /* TLB inconsistency */
331 /* Access violation */
341 /* XXX: we should go on looping to check all TLBs consistency
342 * but we can speed-up the whole thing as the
343 * result would be undefined if TLBs are not consistent.
352 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx
" prot=%01x ret=%d\n",
353 ctx
->raddr
& TARGET_PAGE_MASK
, ctx
->prot
, ret
);
354 /* Update page flags */
355 pte_update_flags(ctx
, &env
->tlb
.tlb6
[best
].pte1
, ret
, rw
);
361 /* Perform BAT hit & translation */
362 static inline void bat_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
363 int *validp
, int *protp
, target_ulong
*BATu
,
369 bl
= (*BATu
& 0x00001FFC) << 15;
372 if (((msr_pr
== 0) && (*BATu
& 0x00000002)) ||
373 ((msr_pr
!= 0) && (*BATu
& 0x00000001))) {
375 pp
= *BATl
& 0x00000003;
377 prot
= PAGE_READ
| PAGE_EXEC
;
388 static int get_bat_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
389 target_ulong
virtual, int rw
, int type
)
391 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
392 target_ulong BEPIl
, BEPIu
, bl
;
396 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx
"\n", __func__
,
397 type
== ACCESS_CODE
? 'I' : 'D', virtual);
400 BATlt
= env
->IBAT
[1];
401 BATut
= env
->IBAT
[0];
404 BATlt
= env
->DBAT
[1];
405 BATut
= env
->DBAT
[0];
408 for (i
= 0; i
< env
->nb_BATs
; i
++) {
411 BEPIu
= *BATu
& 0xF0000000;
412 BEPIl
= *BATu
& 0x0FFE0000;
413 bat_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
414 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
415 " BATl " TARGET_FMT_lx
"\n", __func__
,
416 type
== ACCESS_CODE
? 'I' : 'D', i
, virtual, *BATu
, *BATl
);
417 if ((virtual & 0xF0000000) == BEPIu
&&
418 ((virtual & 0x0FFE0000) & ~bl
) == BEPIl
) {
421 /* Get physical address */
422 ctx
->raddr
= (*BATl
& 0xF0000000) |
423 ((virtual & 0x0FFE0000 & bl
) | (*BATl
& 0x0FFE0000)) |
424 (virtual & 0x0001F000);
425 /* Compute access rights */
427 ret
= check_prot(ctx
->prot
, rw
, type
);
429 LOG_BATS("BAT %d match: r " TARGET_FMT_plx
" prot=%c%c\n",
430 i
, ctx
->raddr
, ctx
->prot
& PAGE_READ
? 'R' : '-',
431 ctx
->prot
& PAGE_WRITE
? 'W' : '-');
438 #if defined(DEBUG_BATS)
439 if (qemu_log_enabled()) {
440 LOG_BATS("no BAT match for " TARGET_FMT_lx
":\n", virtual);
441 for (i
= 0; i
< 4; i
++) {
444 BEPIu
= *BATu
& 0xF0000000;
445 BEPIl
= *BATu
& 0x0FFE0000;
446 bl
= (*BATu
& 0x00001FFC) << 15;
447 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
448 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
449 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
450 __func__
, type
== ACCESS_CODE
? 'I' : 'D', i
, virtual,
451 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
460 /* Perform segment based translation */
461 static inline int get_segment_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
462 target_ulong eaddr
, int rw
, int type
)
466 int ds
, pr
, target_page_bits
;
468 target_ulong sr
, pgidx
;
473 sr
= env
->sr
[eaddr
>> 28];
474 ctx
->key
= (((sr
& 0x20000000) && (pr
!= 0)) ||
475 ((sr
& 0x40000000) && (pr
== 0))) ? 1 : 0;
476 ds
= sr
& 0x80000000 ? 1 : 0;
477 ctx
->nx
= sr
& 0x10000000 ? 1 : 0;
478 vsid
= sr
& 0x00FFFFFF;
479 target_page_bits
= TARGET_PAGE_BITS
;
480 LOG_MMU("Check segment v=" TARGET_FMT_lx
" %d " TARGET_FMT_lx
" nip="
481 TARGET_FMT_lx
" lr=" TARGET_FMT_lx
482 " ir=%d dr=%d pr=%d %d t=%d\n",
483 eaddr
, (int)(eaddr
>> 28), sr
, env
->nip
, env
->lr
, (int)msr_ir
,
484 (int)msr_dr
, pr
!= 0 ? 1 : 0, rw
, type
);
485 pgidx
= (eaddr
& ~SEGMENT_MASK_256M
) >> target_page_bits
;
487 ctx
->ptem
= (vsid
<< 7) | (pgidx
>> 10);
489 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx
"\n",
490 ctx
->key
, ds
, ctx
->nx
, vsid
);
493 /* Check if instruction fetch is allowed, if needed */
494 if (type
!= ACCESS_CODE
|| ctx
->nx
== 0) {
495 /* Page address translation */
496 LOG_MMU("htab_base " TARGET_FMT_plx
" htab_mask " TARGET_FMT_plx
497 " hash " TARGET_FMT_plx
"\n",
498 env
->htab_base
, env
->htab_mask
, hash
);
500 ctx
->hash
[1] = ~hash
;
502 /* Initialize real address with an invalid value */
503 ctx
->raddr
= (hwaddr
)-1ULL;
504 /* Software TLB search */
505 ret
= ppc6xx_tlb_check(env
, ctx
, eaddr
, rw
, type
);
506 #if defined(DUMP_PAGE_TABLES)
507 if (qemu_log_enabled()) {
509 uint32_t a0
, a1
, a2
, a3
;
511 qemu_log("Page table: " TARGET_FMT_plx
" len " TARGET_FMT_plx
512 "\n", sdr
, mask
+ 0x80);
513 for (curaddr
= sdr
; curaddr
< (sdr
+ mask
+ 0x80);
515 a0
= ldl_phys(curaddr
);
516 a1
= ldl_phys(curaddr
+ 4);
517 a2
= ldl_phys(curaddr
+ 8);
518 a3
= ldl_phys(curaddr
+ 12);
519 if (a0
!= 0 || a1
!= 0 || a2
!= 0 || a3
!= 0) {
520 qemu_log(TARGET_FMT_plx
": %08x %08x %08x %08x\n",
521 curaddr
, a0
, a1
, a2
, a3
);
527 LOG_MMU("No access allowed\n");
533 LOG_MMU("direct store...\n");
534 /* Direct-store segment : absolutely *BUGGY* for now */
536 /* Direct-store implies a 32-bit MMU.
537 * Check the Segment Register's bus unit ID (BUID).
539 sr
= env
->sr
[eaddr
>> 28];
540 if ((sr
& 0x1FF00000) >> 20 == 0x07f) {
541 /* Memory-forced I/O controller interface access */
542 /* If T=1 and BUID=x'07F', the 601 performs a memory access
543 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
545 ctx
->raddr
= ((sr
& 0xF) << 28) | (eaddr
& 0x0FFFFFFF);
546 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
552 /* Integer load/store : only access allowed */
555 /* No code fetch is allowed in direct-store areas */
558 /* Floating point load/store */
561 /* lwarx, ldarx or srwcx. */
564 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
565 /* Should make the instruction do no-op.
566 * As it already do no-op, it's quite easy :-)
574 qemu_log("ERROR: instruction should not need "
575 "address translation\n");
578 if ((rw
== 1 || ctx
->key
!= 1) && (rw
== 0 || ctx
->key
!= 0)) {
589 /* Generic TLB check function for embedded PowerPC implementations */
590 static int ppcemb_tlb_check(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
592 target_ulong address
, uint32_t pid
, int ext
,
597 /* Check valid flag */
598 if (!(tlb
->prot
& PAGE_VALID
)) {
601 mask
= ~(tlb
->size
- 1);
602 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx
" PID %u <=> " TARGET_FMT_lx
603 " " TARGET_FMT_lx
" %u %x\n", __func__
, i
, address
, pid
, tlb
->EPN
,
604 mask
, (uint32_t)tlb
->PID
, tlb
->prot
);
606 if (tlb
->PID
!= 0 && tlb
->PID
!= pid
) {
609 /* Check effective address */
610 if ((address
& mask
) != tlb
->EPN
) {
613 *raddrp
= (tlb
->RPN
& mask
) | (address
& ~mask
);
615 /* Extend the physical address to 36 bits */
616 *raddrp
|= (uint64_t)(tlb
->RPN
& 0xF) << 32;
622 /* Generic TLB search function for PowerPC embedded implementations */
623 static int ppcemb_tlb_search(CPUPPCState
*env
, target_ulong address
,
630 /* Default return value is no match */
632 for (i
= 0; i
< env
->nb_tlb
; i
++) {
633 tlb
= &env
->tlb
.tlbe
[i
];
634 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
, pid
, 0, i
) == 0) {
643 /* Helpers specific to PowerPC 40x implementations */
644 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState
*env
)
649 for (i
= 0; i
< env
->nb_tlb
; i
++) {
650 tlb
= &env
->tlb
.tlbe
[i
];
651 tlb
->prot
&= ~PAGE_VALID
;
656 static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState
*env
,
657 target_ulong eaddr
, uint32_t pid
)
659 #if !defined(FLUSH_ALL_TLBS)
662 target_ulong page
, end
;
665 for (i
= 0; i
< env
->nb_tlb
; i
++) {
666 tlb
= &env
->tlb
.tlbe
[i
];
667 if (ppcemb_tlb_check(env
, tlb
, &raddr
, eaddr
, pid
, 0, i
) == 0) {
668 end
= tlb
->EPN
+ tlb
->size
;
669 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
670 tlb_flush_page(env
, page
);
672 tlb
->prot
&= ~PAGE_VALID
;
677 ppc4xx_tlb_invalidate_all(env
);
681 static int mmu40x_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
682 target_ulong address
, int rw
,
687 int i
, ret
, zsel
, zpr
, pr
;
690 raddr
= (hwaddr
)-1ULL;
692 for (i
= 0; i
< env
->nb_tlb
; i
++) {
693 tlb
= &env
->tlb
.tlbe
[i
];
694 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
695 env
->spr
[SPR_40x_PID
], 0, i
) < 0) {
698 zsel
= (tlb
->attr
>> 4) & 0xF;
699 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (30 - (2 * zsel
))) & 0x3;
700 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
701 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
702 /* Check execute enable bit */
710 /* All accesses granted */
711 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
716 /* Raise Zone protection fault. */
717 env
->spr
[SPR_40x_ESR
] = 1 << 22;
725 /* Check from TLB entry */
726 ctx
->prot
= tlb
->prot
;
727 ret
= check_prot(ctx
->prot
, rw
, access_type
);
729 env
->spr
[SPR_40x_ESR
] = 0;
735 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
736 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
741 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
742 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
747 void store_40x_sler(CPUPPCState
*env
, uint32_t val
)
749 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
751 /* XXX: TO BE FIXED */
752 if (val
!= 0x00000000) {
753 cpu_abort(CPU(cpu
), "Little-endian regions are not supported by now\n");
755 env
->spr
[SPR_405_SLER
] = val
;
758 static inline int mmubooke_check_tlb(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
759 hwaddr
*raddr
, int *prot
,
760 target_ulong address
, int rw
,
761 int access_type
, int i
)
765 if (ppcemb_tlb_check(env
, tlb
, raddr
, address
,
766 env
->spr
[SPR_BOOKE_PID
],
767 !env
->nb_pids
, i
) >= 0) {
771 if (env
->spr
[SPR_BOOKE_PID1
] &&
772 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
773 env
->spr
[SPR_BOOKE_PID1
], 0, i
) >= 0) {
777 if (env
->spr
[SPR_BOOKE_PID2
] &&
778 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
779 env
->spr
[SPR_BOOKE_PID2
], 0, i
) >= 0) {
783 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
789 prot2
= tlb
->prot
& 0xF;
791 prot2
= (tlb
->prot
>> 4) & 0xF;
794 /* Check the address space */
795 if (access_type
== ACCESS_CODE
) {
796 if (msr_ir
!= (tlb
->attr
& 1)) {
797 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
802 if (prot2
& PAGE_EXEC
) {
803 LOG_SWTLB("%s: good TLB!\n", __func__
);
807 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
810 if (msr_dr
!= (tlb
->attr
& 1)) {
811 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
816 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
817 LOG_SWTLB("%s: found TLB!\n", __func__
);
821 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
828 static int mmubooke_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
829 target_ulong address
, int rw
,
837 raddr
= (hwaddr
)-1ULL;
838 for (i
= 0; i
< env
->nb_tlb
; i
++) {
839 tlb
= &env
->tlb
.tlbe
[i
];
840 ret
= mmubooke_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
, rw
,
849 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
850 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
853 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
854 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
860 static void booke206_flush_tlb(CPUPPCState
*env
, int flags
,
861 const int check_iprot
)
865 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
867 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
868 if (flags
& (1 << i
)) {
869 tlb_size
= booke206_tlb_size(env
, i
);
870 for (j
= 0; j
< tlb_size
; j
++) {
871 if (!check_iprot
|| !(tlb
[j
].mas1
& MAS1_IPROT
)) {
872 tlb
[j
].mas1
&= ~MAS1_VALID
;
876 tlb
+= booke206_tlb_size(env
, i
);
882 static hwaddr
booke206_tlb_to_page_size(CPUPPCState
*env
,
887 tlbm_size
= (tlb
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
889 return 1024ULL << tlbm_size
;
892 /* TLB check function for MAS based SoftTLBs */
893 static int ppcmas_tlb_check(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
895 target_ulong address
, uint32_t pid
)
900 /* Check valid flag */
901 if (!(tlb
->mas1
& MAS1_VALID
)) {
905 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
906 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx
" PID=0x%x MAS1=0x%x MAS2=0x%"
907 PRIx64
" mask=0x" TARGET_FMT_lx
" MAS7_3=0x%" PRIx64
" MAS8=%x\n",
908 __func__
, address
, pid
, tlb
->mas1
, tlb
->mas2
, mask
, tlb
->mas7_3
,
912 tlb_pid
= (tlb
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
;
913 if (tlb_pid
!= 0 && tlb_pid
!= pid
) {
917 /* Check effective address */
918 if ((address
& mask
) != (tlb
->mas2
& MAS2_EPN_MASK
)) {
923 *raddrp
= (tlb
->mas7_3
& mask
) | (address
& ~mask
);
929 static int mmubooke206_check_tlb(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
930 hwaddr
*raddr
, int *prot
,
931 target_ulong address
, int rw
,
937 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
,
938 env
->spr
[SPR_BOOKE_PID
]) >= 0) {
942 if (env
->spr
[SPR_BOOKE_PID1
] &&
943 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
944 env
->spr
[SPR_BOOKE_PID1
]) >= 0) {
948 if (env
->spr
[SPR_BOOKE_PID2
] &&
949 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
950 env
->spr
[SPR_BOOKE_PID2
]) >= 0) {
954 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
960 if (tlb
->mas7_3
& MAS3_UR
) {
963 if (tlb
->mas7_3
& MAS3_UW
) {
966 if (tlb
->mas7_3
& MAS3_UX
) {
970 if (tlb
->mas7_3
& MAS3_SR
) {
973 if (tlb
->mas7_3
& MAS3_SW
) {
976 if (tlb
->mas7_3
& MAS3_SX
) {
981 /* Check the address space and permissions */
982 if (access_type
== ACCESS_CODE
) {
983 if (msr_ir
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
984 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
989 if (prot2
& PAGE_EXEC
) {
990 LOG_SWTLB("%s: good TLB!\n", __func__
);
994 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
997 if (msr_dr
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
998 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1003 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
1004 LOG_SWTLB("%s: found TLB!\n", __func__
);
1008 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
1015 static int mmubooke206_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1016 target_ulong address
, int rw
,
1024 raddr
= (hwaddr
)-1ULL;
1026 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1027 int ways
= booke206_tlb_ways(env
, i
);
1029 for (j
= 0; j
< ways
; j
++) {
1030 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
1034 ret
= mmubooke206_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
,
1046 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
1047 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1050 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
1051 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
1057 static const char *book3e_tsize_to_str
[32] = {
1058 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1059 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1060 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1064 static void mmubooke_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1067 ppcemb_tlb_t
*entry
;
1070 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1071 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1075 cpu_fprintf(f
, "\nTLB:\n");
1076 cpu_fprintf(f
, "Effective Physical Size PID Prot "
1079 entry
= &env
->tlb
.tlbe
[0];
1080 for (i
= 0; i
< env
->nb_tlb
; i
++, entry
++) {
1083 uint64_t size
= (uint64_t)entry
->size
;
1086 /* Check valid flag */
1087 if (!(entry
->prot
& PAGE_VALID
)) {
1091 mask
= ~(entry
->size
- 1);
1092 ea
= entry
->EPN
& mask
;
1093 pa
= entry
->RPN
& mask
;
1094 /* Extend the physical address to 36 bits */
1095 pa
|= (hwaddr
)(entry
->RPN
& 0xF) << 32;
1098 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"M", size
/ 1024);
1100 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"k", size
);
1102 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %s %-5u %08x %08x\n",
1103 (uint64_t)ea
, (uint64_t)pa
, size_buf
, (uint32_t)entry
->PID
,
1104 entry
->prot
, entry
->attr
);
1109 static void mmubooke206_dump_one_tlb(FILE *f
, fprintf_function cpu_fprintf
,
1110 CPUPPCState
*env
, int tlbn
, int offset
,
1113 ppcmas_tlb_t
*entry
;
1116 cpu_fprintf(f
, "\nTLB%d:\n", tlbn
);
1117 cpu_fprintf(f
, "Effective Physical Size TID TS SRWX"
1118 " URWX WIMGE U0123\n");
1120 entry
= &env
->tlb
.tlbm
[offset
];
1121 for (i
= 0; i
< tlbsize
; i
++, entry
++) {
1122 hwaddr ea
, pa
, size
;
1125 if (!(entry
->mas1
& MAS1_VALID
)) {
1129 tsize
= (entry
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1130 size
= 1024ULL << tsize
;
1131 ea
= entry
->mas2
& ~(size
- 1);
1132 pa
= entry
->mas7_3
& ~(size
- 1);
1134 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %4s %-5u %1u S%c%c%c"
1135 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1136 (uint64_t)ea
, (uint64_t)pa
,
1137 book3e_tsize_to_str
[tsize
],
1138 (entry
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
,
1139 (entry
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
,
1140 entry
->mas7_3
& MAS3_SR
? 'R' : '-',
1141 entry
->mas7_3
& MAS3_SW
? 'W' : '-',
1142 entry
->mas7_3
& MAS3_SX
? 'X' : '-',
1143 entry
->mas7_3
& MAS3_UR
? 'R' : '-',
1144 entry
->mas7_3
& MAS3_UW
? 'W' : '-',
1145 entry
->mas7_3
& MAS3_UX
? 'X' : '-',
1146 entry
->mas2
& MAS2_W
? 'W' : '-',
1147 entry
->mas2
& MAS2_I
? 'I' : '-',
1148 entry
->mas2
& MAS2_M
? 'M' : '-',
1149 entry
->mas2
& MAS2_G
? 'G' : '-',
1150 entry
->mas2
& MAS2_E
? 'E' : '-',
1151 entry
->mas7_3
& MAS3_U0
? '0' : '-',
1152 entry
->mas7_3
& MAS3_U1
? '1' : '-',
1153 entry
->mas7_3
& MAS3_U2
? '2' : '-',
1154 entry
->mas7_3
& MAS3_U3
? '3' : '-');
1158 static void mmubooke206_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1164 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1165 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1169 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1170 int size
= booke206_tlb_size(env
, i
);
1176 mmubooke206_dump_one_tlb(f
, cpu_fprintf
, env
, i
, offset
, size
);
1181 static void mmu6xx_dump_BATs(FILE *f
, fprintf_function cpu_fprintf
,
1182 CPUPPCState
*env
, int type
)
1184 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
1185 target_ulong BEPIl
, BEPIu
, bl
;
1190 BATlt
= env
->IBAT
[1];
1191 BATut
= env
->IBAT
[0];
1194 BATlt
= env
->DBAT
[1];
1195 BATut
= env
->DBAT
[0];
1199 for (i
= 0; i
< env
->nb_BATs
; i
++) {
1202 BEPIu
= *BATu
& 0xF0000000;
1203 BEPIl
= *BATu
& 0x0FFE0000;
1204 bl
= (*BATu
& 0x00001FFC) << 15;
1205 cpu_fprintf(f
, "%s BAT%d BATu " TARGET_FMT_lx
1206 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
1207 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
1208 type
== ACCESS_CODE
? "code" : "data", i
,
1209 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
1213 static void mmu6xx_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1218 int type
, way
, entry
, i
;
1220 cpu_fprintf(f
, "HTAB base = 0x%"HWADDR_PRIx
"\n", env
->htab_base
);
1221 cpu_fprintf(f
, "HTAB mask = 0x%"HWADDR_PRIx
"\n", env
->htab_mask
);
1223 cpu_fprintf(f
, "\nSegment registers:\n");
1224 for (i
= 0; i
< 32; i
++) {
1226 if (sr
& 0x80000000) {
1227 cpu_fprintf(f
, "%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1228 "CNTLR_SPEC=0x%05x\n", i
,
1229 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1230 sr
& 0x20000000 ? 1 : 0, (uint32_t)((sr
>> 20) & 0x1FF),
1231 (uint32_t)(sr
& 0xFFFFF));
1233 cpu_fprintf(f
, "%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i
,
1234 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1235 sr
& 0x20000000 ? 1 : 0, sr
& 0x10000000 ? 1 : 0,
1236 (uint32_t)(sr
& 0x00FFFFFF));
1240 cpu_fprintf(f
, "\nBATs:\n");
1241 mmu6xx_dump_BATs(f
, cpu_fprintf
, env
, ACCESS_INT
);
1242 mmu6xx_dump_BATs(f
, cpu_fprintf
, env
, ACCESS_CODE
);
1244 if (env
->id_tlbs
!= 1) {
1245 cpu_fprintf(f
, "ERROR: 6xx MMU should have separated TLB"
1246 " for code and data\n");
1249 cpu_fprintf(f
, "\nTLBs [EPN EPN + SIZE]\n");
1251 for (type
= 0; type
< 2; type
++) {
1252 for (way
= 0; way
< env
->nb_ways
; way
++) {
1253 for (entry
= env
->nb_tlb
* type
+ env
->tlb_per_way
* way
;
1254 entry
< (env
->nb_tlb
* type
+ env
->tlb_per_way
* (way
+ 1));
1257 tlb
= &env
->tlb
.tlb6
[entry
];
1258 cpu_fprintf(f
, "%s TLB %02d/%02d way:%d %s ["
1259 TARGET_FMT_lx
" " TARGET_FMT_lx
"]\n",
1260 type
? "code" : "data", entry
% env
->nb_tlb
,
1262 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
1263 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
);
1269 void dump_mmu(FILE *f
, fprintf_function cpu_fprintf
, CPUPPCState
*env
)
1271 switch (env
->mmu_model
) {
1272 case POWERPC_MMU_BOOKE
:
1273 mmubooke_dump_mmu(f
, cpu_fprintf
, env
);
1275 case POWERPC_MMU_BOOKE206
:
1276 mmubooke206_dump_mmu(f
, cpu_fprintf
, env
);
1278 case POWERPC_MMU_SOFT_6xx
:
1279 case POWERPC_MMU_SOFT_74xx
:
1280 mmu6xx_dump_mmu(f
, cpu_fprintf
, env
);
1282 #if defined(TARGET_PPC64)
1283 case POWERPC_MMU_64B
:
1284 case POWERPC_MMU_2_06
:
1285 case POWERPC_MMU_2_06a
:
1286 case POWERPC_MMU_2_06d
:
1287 dump_slb(f
, cpu_fprintf
, env
);
1291 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented\n", __func__
);
1295 static inline int check_physical(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1296 target_ulong eaddr
, int rw
)
1301 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1303 switch (env
->mmu_model
) {
1304 case POWERPC_MMU_SOFT_6xx
:
1305 case POWERPC_MMU_SOFT_74xx
:
1306 case POWERPC_MMU_SOFT_4xx
:
1307 case POWERPC_MMU_REAL
:
1308 case POWERPC_MMU_BOOKE
:
1309 ctx
->prot
|= PAGE_WRITE
;
1312 case POWERPC_MMU_SOFT_4xx_Z
:
1313 if (unlikely(msr_pe
!= 0)) {
1314 /* 403 family add some particular protections,
1315 * using PBL/PBU registers for accesses with no translation.
1318 /* Check PLB validity */
1319 (env
->pb
[0] < env
->pb
[1] &&
1320 /* and address in plb area */
1321 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1322 (env
->pb
[2] < env
->pb
[3] &&
1323 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1324 if (in_plb
^ msr_px
) {
1325 /* Access in protected area */
1327 /* Access is not allowed */
1331 /* Read-write access is allowed */
1332 ctx
->prot
|= PAGE_WRITE
;
1338 /* Caller's checks mean we should never get here for other models */
1346 static int get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1347 target_ulong eaddr
, int rw
, int access_type
)
1349 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1351 bool real_mode
= (access_type
== ACCESS_CODE
&& msr_ir
== 0)
1352 || (access_type
!= ACCESS_CODE
&& msr_dr
== 0);
1355 qemu_log("%s\n", __func__
);
1358 switch (env
->mmu_model
) {
1359 case POWERPC_MMU_SOFT_6xx
:
1360 case POWERPC_MMU_SOFT_74xx
:
1362 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1364 /* Try to find a BAT */
1365 if (env
->nb_BATs
!= 0) {
1366 ret
= get_bat_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1369 /* We didn't match any BAT entry or don't have BATs */
1370 ret
= get_segment_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1375 case POWERPC_MMU_SOFT_4xx
:
1376 case POWERPC_MMU_SOFT_4xx_Z
:
1378 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1380 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1384 case POWERPC_MMU_BOOKE
:
1385 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1388 case POWERPC_MMU_BOOKE206
:
1389 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1392 case POWERPC_MMU_MPC8xx
:
1394 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1396 case POWERPC_MMU_REAL
:
1398 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1400 cpu_abort(CPU(cpu
), "PowerPC in real mode do not do any translation\n");
1404 cpu_abort(CPU(cpu
), "Unknown or invalid MMU model\n");
1408 qemu_log("%s address " TARGET_FMT_lx
" => %d " TARGET_FMT_plx
"\n",
1409 __func__
, eaddr
, ret
, ctx
->raddr
);
1415 hwaddr
ppc_cpu_get_phys_page_debug(CPUState
*cs
, vaddr addr
)
1417 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
1418 CPUPPCState
*env
= &cpu
->env
;
1421 switch (env
->mmu_model
) {
1422 #if defined(TARGET_PPC64)
1423 case POWERPC_MMU_64B
:
1424 case POWERPC_MMU_2_06
:
1425 case POWERPC_MMU_2_06a
:
1426 case POWERPC_MMU_2_06d
:
1427 return ppc_hash64_get_phys_page_debug(env
, addr
);
1430 case POWERPC_MMU_32B
:
1431 case POWERPC_MMU_601
:
1432 return ppc_hash32_get_phys_page_debug(env
, addr
);
1438 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0)) {
1440 /* Some MMUs have separate TLBs for code and data. If we only try an
1441 * ACCESS_INT, we may not be able to read instructions mapped by code
1442 * TLBs, so we also try a ACCESS_CODE.
1444 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0,
1445 ACCESS_CODE
) != 0)) {
1450 return ctx
.raddr
& TARGET_PAGE_MASK
;
1453 static void booke206_update_mas_tlb_miss(CPUPPCState
*env
, target_ulong address
,
1456 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
1457 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
1458 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
1459 env
->spr
[SPR_BOOKE_MAS3
] = 0;
1460 env
->spr
[SPR_BOOKE_MAS6
] = 0;
1461 env
->spr
[SPR_BOOKE_MAS7
] = 0;
1464 if (((rw
== 2) && msr_ir
) || ((rw
!= 2) && msr_dr
)) {
1465 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
1466 env
->spr
[SPR_BOOKE_MAS6
] |= MAS6_SAS
;
1469 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_VALID
;
1470 env
->spr
[SPR_BOOKE_MAS2
] |= address
& MAS2_EPN_MASK
;
1472 switch (env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TIDSELD_PIDZ
) {
1473 case MAS4_TIDSELD_PID0
:
1474 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID
] << MAS1_TID_SHIFT
;
1476 case MAS4_TIDSELD_PID1
:
1477 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID1
] << MAS1_TID_SHIFT
;
1479 case MAS4_TIDSELD_PID2
:
1480 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID2
] << MAS1_TID_SHIFT
;
1484 env
->spr
[SPR_BOOKE_MAS6
] |= env
->spr
[SPR_BOOKE_PID
] << 16;
1486 /* next victim logic */
1487 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
1489 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
1490 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
1493 /* Perform address translation */
1494 static int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
,
1495 int rw
, int mmu_idx
)
1497 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1505 access_type
= ACCESS_CODE
;
1508 access_type
= env
->access_type
;
1510 ret
= get_physical_address(env
, &ctx
, address
, rw
, access_type
);
1512 tlb_set_page(env
, address
& TARGET_PAGE_MASK
,
1513 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1514 mmu_idx
, TARGET_PAGE_SIZE
);
1516 } else if (ret
< 0) {
1518 if (access_type
== ACCESS_CODE
) {
1521 /* No matches in page tables or TLB */
1522 switch (env
->mmu_model
) {
1523 case POWERPC_MMU_SOFT_6xx
:
1524 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1525 env
->error_code
= 1 << 18;
1526 env
->spr
[SPR_IMISS
] = address
;
1527 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1529 case POWERPC_MMU_SOFT_74xx
:
1530 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1532 case POWERPC_MMU_SOFT_4xx
:
1533 case POWERPC_MMU_SOFT_4xx_Z
:
1534 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1535 env
->error_code
= 0;
1536 env
->spr
[SPR_40x_DEAR
] = address
;
1537 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1539 case POWERPC_MMU_BOOKE206
:
1540 booke206_update_mas_tlb_miss(env
, address
, rw
);
1542 case POWERPC_MMU_BOOKE
:
1543 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1544 env
->error_code
= 0;
1545 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1547 case POWERPC_MMU_MPC8xx
:
1549 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1551 case POWERPC_MMU_REAL
:
1552 cpu_abort(cs
, "PowerPC in real mode should never raise "
1553 "any MMU exceptions\n");
1556 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1561 /* Access rights violation */
1562 cs
->exception_index
= POWERPC_EXCP_ISI
;
1563 env
->error_code
= 0x08000000;
1566 /* No execute protection violation */
1567 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1568 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1569 env
->spr
[SPR_BOOKE_ESR
] = 0x00000000;
1571 cs
->exception_index
= POWERPC_EXCP_ISI
;
1572 env
->error_code
= 0x10000000;
1575 /* Direct store exception */
1576 /* No code fetch is allowed in direct-store areas */
1577 cs
->exception_index
= POWERPC_EXCP_ISI
;
1578 env
->error_code
= 0x10000000;
1584 /* No matches in page tables or TLB */
1585 switch (env
->mmu_model
) {
1586 case POWERPC_MMU_SOFT_6xx
:
1588 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1589 env
->error_code
= 1 << 16;
1591 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1592 env
->error_code
= 0;
1594 env
->spr
[SPR_DMISS
] = address
;
1595 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1597 env
->error_code
|= ctx
.key
<< 19;
1598 env
->spr
[SPR_HASH1
] = env
->htab_base
+
1599 get_pteg_offset32(env
, ctx
.hash
[0]);
1600 env
->spr
[SPR_HASH2
] = env
->htab_base
+
1601 get_pteg_offset32(env
, ctx
.hash
[1]);
1603 case POWERPC_MMU_SOFT_74xx
:
1605 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1607 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1610 /* Implement LRU algorithm */
1611 env
->error_code
= ctx
.key
<< 19;
1612 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1613 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1614 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1616 case POWERPC_MMU_SOFT_4xx
:
1617 case POWERPC_MMU_SOFT_4xx_Z
:
1618 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1619 env
->error_code
= 0;
1620 env
->spr
[SPR_40x_DEAR
] = address
;
1622 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1624 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1627 case POWERPC_MMU_MPC8xx
:
1629 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1631 case POWERPC_MMU_BOOKE206
:
1632 booke206_update_mas_tlb_miss(env
, address
, rw
);
1634 case POWERPC_MMU_BOOKE
:
1635 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1636 env
->error_code
= 0;
1637 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1638 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1640 case POWERPC_MMU_REAL
:
1641 cpu_abort(cs
, "PowerPC in real mode should never raise "
1642 "any MMU exceptions\n");
1645 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1650 /* Access rights violation */
1651 cs
->exception_index
= POWERPC_EXCP_DSI
;
1652 env
->error_code
= 0;
1653 if (env
->mmu_model
== POWERPC_MMU_SOFT_4xx
1654 || env
->mmu_model
== POWERPC_MMU_SOFT_4xx_Z
) {
1655 env
->spr
[SPR_40x_DEAR
] = address
;
1657 env
->spr
[SPR_40x_ESR
] |= 0x00800000;
1659 } else if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1660 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1661 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1662 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1664 env
->spr
[SPR_DAR
] = address
;
1666 env
->spr
[SPR_DSISR
] = 0x0A000000;
1668 env
->spr
[SPR_DSISR
] = 0x08000000;
1673 /* Direct store exception */
1674 switch (access_type
) {
1676 /* Floating point load/store */
1677 cs
->exception_index
= POWERPC_EXCP_ALIGN
;
1678 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1679 env
->spr
[SPR_DAR
] = address
;
1682 /* lwarx, ldarx or stwcx. */
1683 cs
->exception_index
= POWERPC_EXCP_DSI
;
1684 env
->error_code
= 0;
1685 env
->spr
[SPR_DAR
] = address
;
1687 env
->spr
[SPR_DSISR
] = 0x06000000;
1689 env
->spr
[SPR_DSISR
] = 0x04000000;
1693 /* eciwx or ecowx */
1694 cs
->exception_index
= POWERPC_EXCP_DSI
;
1695 env
->error_code
= 0;
1696 env
->spr
[SPR_DAR
] = address
;
1698 env
->spr
[SPR_DSISR
] = 0x06100000;
1700 env
->spr
[SPR_DSISR
] = 0x04100000;
1704 printf("DSI: invalid exception (%d)\n", ret
);
1705 cs
->exception_index
= POWERPC_EXCP_PROGRAM
;
1707 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1708 env
->spr
[SPR_DAR
] = address
;
1715 printf("%s: set exception to %d %02x\n", __func__
,
1716 cs
->exception
, env
->error_code
);
1724 /*****************************************************************************/
1725 /* BATs management */
1726 #if !defined(FLUSH_ALL_TLBS)
1727 static inline void do_invalidate_BAT(CPUPPCState
*env
, target_ulong BATu
,
1730 target_ulong base
, end
, page
;
1732 base
= BATu
& ~0x0001FFFF;
1733 end
= base
+ mask
+ 0x00020000;
1734 LOG_BATS("Flush BAT from " TARGET_FMT_lx
" to " TARGET_FMT_lx
" ("
1735 TARGET_FMT_lx
")\n", base
, end
, mask
);
1736 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
1737 tlb_flush_page(env
, page
);
1739 LOG_BATS("Flush done\n");
1743 static inline void dump_store_bat(CPUPPCState
*env
, char ID
, int ul
, int nr
,
1746 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx
" (" TARGET_FMT_lx
")\n", ID
,
1747 nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1750 void helper_store_ibatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1754 dump_store_bat(env
, 'I', 0, nr
, value
);
1755 if (env
->IBAT
[0][nr
] != value
) {
1756 mask
= (value
<< 15) & 0x0FFE0000UL
;
1757 #if !defined(FLUSH_ALL_TLBS)
1758 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1760 /* When storing valid upper BAT, mask BEPI and BRPN
1761 * and invalidate all TLBs covered by this BAT
1763 mask
= (value
<< 15) & 0x0FFE0000UL
;
1764 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1765 (value
& ~0x0001FFFFUL
& ~mask
);
1766 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1767 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1768 #if !defined(FLUSH_ALL_TLBS)
1769 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1776 void helper_store_ibatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1778 dump_store_bat(env
, 'I', 1, nr
, value
);
1779 env
->IBAT
[1][nr
] = value
;
1782 void helper_store_dbatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1786 dump_store_bat(env
, 'D', 0, nr
, value
);
1787 if (env
->DBAT
[0][nr
] != value
) {
1788 /* When storing valid upper BAT, mask BEPI and BRPN
1789 * and invalidate all TLBs covered by this BAT
1791 mask
= (value
<< 15) & 0x0FFE0000UL
;
1792 #if !defined(FLUSH_ALL_TLBS)
1793 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1795 mask
= (value
<< 15) & 0x0FFE0000UL
;
1796 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1797 (value
& ~0x0001FFFFUL
& ~mask
);
1798 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1799 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1800 #if !defined(FLUSH_ALL_TLBS)
1801 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1808 void helper_store_dbatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1810 dump_store_bat(env
, 'D', 1, nr
, value
);
1811 env
->DBAT
[1][nr
] = value
;
1814 void helper_store_601_batu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1817 #if defined(FLUSH_ALL_TLBS)
1821 dump_store_bat(env
, 'I', 0, nr
, value
);
1822 if (env
->IBAT
[0][nr
] != value
) {
1823 #if defined(FLUSH_ALL_TLBS)
1826 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1827 if (env
->IBAT
[1][nr
] & 0x40) {
1828 /* Invalidate BAT only if it is valid */
1829 #if !defined(FLUSH_ALL_TLBS)
1830 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1835 /* When storing valid upper BAT, mask BEPI and BRPN
1836 * and invalidate all TLBs covered by this BAT
1838 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1839 (value
& ~0x0001FFFFUL
& ~mask
);
1840 env
->DBAT
[0][nr
] = env
->IBAT
[0][nr
];
1841 if (env
->IBAT
[1][nr
] & 0x40) {
1842 #if !defined(FLUSH_ALL_TLBS)
1843 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1848 #if defined(FLUSH_ALL_TLBS)
1856 void helper_store_601_batl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1858 #if !defined(FLUSH_ALL_TLBS)
1864 dump_store_bat(env
, 'I', 1, nr
, value
);
1865 if (env
->IBAT
[1][nr
] != value
) {
1866 #if defined(FLUSH_ALL_TLBS)
1869 if (env
->IBAT
[1][nr
] & 0x40) {
1870 #if !defined(FLUSH_ALL_TLBS)
1871 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1872 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1878 #if !defined(FLUSH_ALL_TLBS)
1879 mask
= (value
<< 17) & 0x0FFE0000UL
;
1880 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1885 env
->IBAT
[1][nr
] = value
;
1886 env
->DBAT
[1][nr
] = value
;
1887 #if defined(FLUSH_ALL_TLBS)
1895 /*****************************************************************************/
1896 /* TLB management */
1897 void ppc_tlb_invalidate_all(CPUPPCState
*env
)
1899 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1901 switch (env
->mmu_model
) {
1902 case POWERPC_MMU_SOFT_6xx
:
1903 case POWERPC_MMU_SOFT_74xx
:
1904 ppc6xx_tlb_invalidate_all(env
);
1906 case POWERPC_MMU_SOFT_4xx
:
1907 case POWERPC_MMU_SOFT_4xx_Z
:
1908 ppc4xx_tlb_invalidate_all(env
);
1910 case POWERPC_MMU_REAL
:
1911 cpu_abort(CPU(cpu
), "No TLB for PowerPC 4xx in real mode\n");
1913 case POWERPC_MMU_MPC8xx
:
1915 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1917 case POWERPC_MMU_BOOKE
:
1920 case POWERPC_MMU_BOOKE206
:
1921 booke206_flush_tlb(env
, -1, 0);
1923 case POWERPC_MMU_32B
:
1924 case POWERPC_MMU_601
:
1925 #if defined(TARGET_PPC64)
1926 case POWERPC_MMU_64B
:
1927 case POWERPC_MMU_2_06
:
1928 case POWERPC_MMU_2_06a
:
1929 case POWERPC_MMU_2_06d
:
1930 #endif /* defined(TARGET_PPC64) */
1935 cpu_abort(CPU(cpu
), "Unknown MMU model\n");
1940 void ppc_tlb_invalidate_one(CPUPPCState
*env
, target_ulong addr
)
1942 #if !defined(FLUSH_ALL_TLBS)
1943 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1945 addr
&= TARGET_PAGE_MASK
;
1946 switch (env
->mmu_model
) {
1947 case POWERPC_MMU_SOFT_6xx
:
1948 case POWERPC_MMU_SOFT_74xx
:
1949 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
1950 if (env
->id_tlbs
== 1) {
1951 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
1954 case POWERPC_MMU_SOFT_4xx
:
1955 case POWERPC_MMU_SOFT_4xx_Z
:
1956 ppc4xx_tlb_invalidate_virt(env
, addr
, env
->spr
[SPR_40x_PID
]);
1958 case POWERPC_MMU_REAL
:
1959 cpu_abort(CPU(cpu
), "No TLB for PowerPC 4xx in real mode\n");
1961 case POWERPC_MMU_MPC8xx
:
1963 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1965 case POWERPC_MMU_BOOKE
:
1967 cpu_abort(CPU(cpu
), "BookE MMU model is not implemented\n");
1969 case POWERPC_MMU_BOOKE206
:
1971 cpu_abort(CPU(cpu
), "BookE 2.06 MMU model is not implemented\n");
1973 case POWERPC_MMU_32B
:
1974 case POWERPC_MMU_601
:
1975 /* tlbie invalidate TLBs for all segments */
1976 addr
&= ~((target_ulong
)-1ULL << 28);
1977 /* XXX: this case should be optimized,
1978 * giving a mask to tlb_flush_page
1980 tlb_flush_page(env
, addr
| (0x0 << 28));
1981 tlb_flush_page(env
, addr
| (0x1 << 28));
1982 tlb_flush_page(env
, addr
| (0x2 << 28));
1983 tlb_flush_page(env
, addr
| (0x3 << 28));
1984 tlb_flush_page(env
, addr
| (0x4 << 28));
1985 tlb_flush_page(env
, addr
| (0x5 << 28));
1986 tlb_flush_page(env
, addr
| (0x6 << 28));
1987 tlb_flush_page(env
, addr
| (0x7 << 28));
1988 tlb_flush_page(env
, addr
| (0x8 << 28));
1989 tlb_flush_page(env
, addr
| (0x9 << 28));
1990 tlb_flush_page(env
, addr
| (0xA << 28));
1991 tlb_flush_page(env
, addr
| (0xB << 28));
1992 tlb_flush_page(env
, addr
| (0xC << 28));
1993 tlb_flush_page(env
, addr
| (0xD << 28));
1994 tlb_flush_page(env
, addr
| (0xE << 28));
1995 tlb_flush_page(env
, addr
| (0xF << 28));
1997 #if defined(TARGET_PPC64)
1998 case POWERPC_MMU_64B
:
1999 case POWERPC_MMU_2_06
:
2000 case POWERPC_MMU_2_06a
:
2001 case POWERPC_MMU_2_06d
:
2002 /* tlbie invalidate TLBs for all segments */
2003 /* XXX: given the fact that there are too many segments to invalidate,
2004 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
2005 * we just invalidate all TLBs
2009 #endif /* defined(TARGET_PPC64) */
2012 cpu_abort(CPU(cpu
), "Unknown MMU model\n");
2016 ppc_tlb_invalidate_all(env
);
2020 /*****************************************************************************/
2021 /* Special registers manipulation */
2022 void ppc_store_sdr1(CPUPPCState
*env
, target_ulong value
)
2024 LOG_MMU("%s: " TARGET_FMT_lx
"\n", __func__
, value
);
2025 assert(!env
->external_htab
);
2026 if (env
->spr
[SPR_SDR1
] != value
) {
2027 env
->spr
[SPR_SDR1
] = value
;
2028 #if defined(TARGET_PPC64)
2029 if (env
->mmu_model
& POWERPC_MMU_64
) {
2030 target_ulong htabsize
= value
& SDR_64_HTABSIZE
;
2032 if (htabsize
> 28) {
2033 fprintf(stderr
, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2034 " stored in SDR1\n", htabsize
);
2037 env
->htab_mask
= (1ULL << (htabsize
+ 18 - 7)) - 1;
2038 env
->htab_base
= value
& SDR_64_HTABORG
;
2040 #endif /* defined(TARGET_PPC64) */
2042 /* FIXME: Should check for valid HTABMASK values */
2043 env
->htab_mask
= ((value
& SDR_32_HTABMASK
) << 16) | 0xFFFF;
2044 env
->htab_base
= value
& SDR_32_HTABORG
;
2050 /* Segment registers load and store */
2051 target_ulong
helper_load_sr(CPUPPCState
*env
, target_ulong sr_num
)
2053 #if defined(TARGET_PPC64)
2054 if (env
->mmu_model
& POWERPC_MMU_64
) {
2059 return env
->sr
[sr_num
];
2062 void helper_store_sr(CPUPPCState
*env
, target_ulong srnum
, target_ulong value
)
2064 LOG_MMU("%s: reg=%d " TARGET_FMT_lx
" " TARGET_FMT_lx
"\n", __func__
,
2065 (int)srnum
, value
, env
->sr
[srnum
]);
2066 #if defined(TARGET_PPC64)
2067 if (env
->mmu_model
& POWERPC_MMU_64
) {
2068 uint64_t rb
= 0, rs
= 0;
2071 rb
|= ((uint32_t)srnum
& 0xf) << 28;
2072 /* Set the valid bit */
2075 rb
|= (uint32_t)srnum
;
2078 rs
|= (value
& 0xfffffff) << 12;
2080 rs
|= ((value
>> 27) & 0xf) << 8;
2082 ppc_store_slb(env
, rb
, rs
);
2085 if (env
->sr
[srnum
] != value
) {
2086 env
->sr
[srnum
] = value
;
2087 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2088 flusing the whole TLB. */
2089 #if !defined(FLUSH_ALL_TLBS) && 0
2091 target_ulong page
, end
;
2092 /* Invalidate 256 MB of virtual memory */
2093 page
= (16 << 20) * srnum
;
2094 end
= page
+ (16 << 20);
2095 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
2096 tlb_flush_page(env
, page
);
2105 /* TLB management */
2106 void helper_tlbia(CPUPPCState
*env
)
2108 ppc_tlb_invalidate_all(env
);
2111 void helper_tlbie(CPUPPCState
*env
, target_ulong addr
)
2113 ppc_tlb_invalidate_one(env
, addr
);
2116 /* Software driven TLBs management */
2117 /* PowerPC 602/603 software TLB load instructions helpers */
2118 static void do_6xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2120 target_ulong RPN
, CMP
, EPN
;
2123 RPN
= env
->spr
[SPR_RPA
];
2125 CMP
= env
->spr
[SPR_ICMP
];
2126 EPN
= env
->spr
[SPR_IMISS
];
2128 CMP
= env
->spr
[SPR_DCMP
];
2129 EPN
= env
->spr
[SPR_DMISS
];
2131 way
= (env
->spr
[SPR_SRR1
] >> 17) & 1;
2132 (void)EPN
; /* avoid a compiler warning */
2133 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2134 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2136 /* Store this TLB */
2137 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2138 way
, is_code
, CMP
, RPN
);
2141 void helper_6xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2143 do_6xx_tlb(env
, EPN
, 0);
2146 void helper_6xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2148 do_6xx_tlb(env
, EPN
, 1);
2151 /* PowerPC 74xx software TLB load instructions helpers */
2152 static void do_74xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2154 target_ulong RPN
, CMP
, EPN
;
2157 RPN
= env
->spr
[SPR_PTELO
];
2158 CMP
= env
->spr
[SPR_PTEHI
];
2159 EPN
= env
->spr
[SPR_TLBMISS
] & ~0x3;
2160 way
= env
->spr
[SPR_TLBMISS
] & 0x3;
2161 (void)EPN
; /* avoid a compiler warning */
2162 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2163 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2165 /* Store this TLB */
2166 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2167 way
, is_code
, CMP
, RPN
);
2170 void helper_74xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2172 do_74xx_tlb(env
, EPN
, 0);
2175 void helper_74xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2177 do_74xx_tlb(env
, EPN
, 1);
2180 /*****************************************************************************/
2181 /* PowerPC 601 specific instructions (POWER bridge) */
2183 target_ulong
helper_rac(CPUPPCState
*env
, target_ulong addr
)
2187 target_ulong ret
= 0;
2189 /* We don't have to generate many instances of this instruction,
2190 * as rac is supervisor only.
2192 /* XXX: FIX THIS: Pretend we have no BAT */
2193 nb_BATs
= env
->nb_BATs
;
2195 if (get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) == 0) {
2198 env
->nb_BATs
= nb_BATs
;
2202 static inline target_ulong
booke_tlb_to_page_size(int size
)
2204 return 1024 << (2 * size
);
2207 static inline int booke_page_size_to_tlb(target_ulong page_size
)
2211 switch (page_size
) {
2245 #if defined(TARGET_PPC64)
2246 case 0x000100000000ULL
:
2249 case 0x000400000000ULL
:
2252 case 0x001000000000ULL
:
2255 case 0x004000000000ULL
:
2258 case 0x010000000000ULL
:
2270 /* Helpers for 4xx TLB management */
2271 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2273 #define PPC4XX_TLBHI_V 0x00000040
2274 #define PPC4XX_TLBHI_E 0x00000020
2275 #define PPC4XX_TLBHI_SIZE_MIN 0
2276 #define PPC4XX_TLBHI_SIZE_MAX 7
2277 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2278 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2279 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2281 #define PPC4XX_TLBLO_EX 0x00000200
2282 #define PPC4XX_TLBLO_WR 0x00000100
2283 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2284 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2286 target_ulong
helper_4xx_tlbre_hi(CPUPPCState
*env
, target_ulong entry
)
2292 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2293 tlb
= &env
->tlb
.tlbe
[entry
];
2295 if (tlb
->prot
& PAGE_VALID
) {
2296 ret
|= PPC4XX_TLBHI_V
;
2298 size
= booke_page_size_to_tlb(tlb
->size
);
2299 if (size
< PPC4XX_TLBHI_SIZE_MIN
|| size
> PPC4XX_TLBHI_SIZE_MAX
) {
2300 size
= PPC4XX_TLBHI_SIZE_DEFAULT
;
2302 ret
|= size
<< PPC4XX_TLBHI_SIZE_SHIFT
;
2303 env
->spr
[SPR_40x_PID
] = tlb
->PID
;
2307 target_ulong
helper_4xx_tlbre_lo(CPUPPCState
*env
, target_ulong entry
)
2312 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2313 tlb
= &env
->tlb
.tlbe
[entry
];
2315 if (tlb
->prot
& PAGE_EXEC
) {
2316 ret
|= PPC4XX_TLBLO_EX
;
2318 if (tlb
->prot
& PAGE_WRITE
) {
2319 ret
|= PPC4XX_TLBLO_WR
;
2324 void helper_4xx_tlbwe_hi(CPUPPCState
*env
, target_ulong entry
,
2327 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2329 target_ulong page
, end
;
2331 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2333 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2334 tlb
= &env
->tlb
.tlbe
[entry
];
2335 /* Invalidate previous TLB (if it's valid) */
2336 if (tlb
->prot
& PAGE_VALID
) {
2337 end
= tlb
->EPN
+ tlb
->size
;
2338 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx
" end "
2339 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2340 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2341 tlb_flush_page(env
, page
);
2344 tlb
->size
= booke_tlb_to_page_size((val
>> PPC4XX_TLBHI_SIZE_SHIFT
)
2345 & PPC4XX_TLBHI_SIZE_MASK
);
2346 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2347 * If this ever occurs, one should use the ppcemb target instead
2348 * of the ppc or ppc64 one
2350 if ((val
& PPC4XX_TLBHI_V
) && tlb
->size
< TARGET_PAGE_SIZE
) {
2351 cpu_abort(CPU(cpu
), "TLB size " TARGET_FMT_lu
" < %u "
2352 "are not supported (%d)\n",
2353 tlb
->size
, TARGET_PAGE_SIZE
, (int)((val
>> 7) & 0x7));
2355 tlb
->EPN
= val
& ~(tlb
->size
- 1);
2356 if (val
& PPC4XX_TLBHI_V
) {
2357 tlb
->prot
|= PAGE_VALID
;
2358 if (val
& PPC4XX_TLBHI_E
) {
2359 /* XXX: TO BE FIXED */
2361 "Little-endian TLB entries are not supported by now\n");
2364 tlb
->prot
&= ~PAGE_VALID
;
2366 tlb
->PID
= env
->spr
[SPR_40x_PID
]; /* PID */
2367 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2368 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2369 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2370 tlb
->prot
& PAGE_READ
? 'r' : '-',
2371 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2372 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2373 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2374 /* Invalidate new TLB (if valid) */
2375 if (tlb
->prot
& PAGE_VALID
) {
2376 end
= tlb
->EPN
+ tlb
->size
;
2377 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx
" end "
2378 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2379 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2380 tlb_flush_page(env
, page
);
2385 void helper_4xx_tlbwe_lo(CPUPPCState
*env
, target_ulong entry
,
2390 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2392 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2393 tlb
= &env
->tlb
.tlbe
[entry
];
2394 tlb
->attr
= val
& PPC4XX_TLBLO_ATTR_MASK
;
2395 tlb
->RPN
= val
& PPC4XX_TLBLO_RPN_MASK
;
2396 tlb
->prot
= PAGE_READ
;
2397 if (val
& PPC4XX_TLBLO_EX
) {
2398 tlb
->prot
|= PAGE_EXEC
;
2400 if (val
& PPC4XX_TLBLO_WR
) {
2401 tlb
->prot
|= PAGE_WRITE
;
2403 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2404 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2405 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2406 tlb
->prot
& PAGE_READ
? 'r' : '-',
2407 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2408 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2409 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2412 target_ulong
helper_4xx_tlbsx(CPUPPCState
*env
, target_ulong address
)
2414 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_40x_PID
]);
2417 /* PowerPC 440 TLB management */
2418 void helper_440_tlbwe(CPUPPCState
*env
, uint32_t word
, target_ulong entry
,
2422 target_ulong EPN
, RPN
, size
;
2425 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx
"\n",
2426 __func__
, word
, (int)entry
, value
);
2429 tlb
= &env
->tlb
.tlbe
[entry
];
2432 /* Just here to please gcc */
2434 EPN
= value
& 0xFFFFFC00;
2435 if ((tlb
->prot
& PAGE_VALID
) && EPN
!= tlb
->EPN
) {
2439 size
= booke_tlb_to_page_size((value
>> 4) & 0xF);
2440 if ((tlb
->prot
& PAGE_VALID
) && tlb
->size
< size
) {
2445 tlb
->attr
|= (value
>> 8) & 1;
2446 if (value
& 0x200) {
2447 tlb
->prot
|= PAGE_VALID
;
2449 if (tlb
->prot
& PAGE_VALID
) {
2450 tlb
->prot
&= ~PAGE_VALID
;
2454 tlb
->PID
= env
->spr
[SPR_440_MMUCR
] & 0x000000FF;
2455 if (do_flush_tlbs
) {
2460 RPN
= value
& 0xFFFFFC0F;
2461 if ((tlb
->prot
& PAGE_VALID
) && tlb
->RPN
!= RPN
) {
2467 tlb
->attr
= (tlb
->attr
& 0x1) | (value
& 0x0000FF00);
2468 tlb
->prot
= tlb
->prot
& PAGE_VALID
;
2470 tlb
->prot
|= PAGE_READ
<< 4;
2473 tlb
->prot
|= PAGE_WRITE
<< 4;
2476 tlb
->prot
|= PAGE_EXEC
<< 4;
2479 tlb
->prot
|= PAGE_READ
;
2482 tlb
->prot
|= PAGE_WRITE
;
2485 tlb
->prot
|= PAGE_EXEC
;
2491 target_ulong
helper_440_tlbre(CPUPPCState
*env
, uint32_t word
,
2499 tlb
= &env
->tlb
.tlbe
[entry
];
2502 /* Just here to please gcc */
2505 size
= booke_page_size_to_tlb(tlb
->size
);
2506 if (size
< 0 || size
> 0xF) {
2510 if (tlb
->attr
& 0x1) {
2513 if (tlb
->prot
& PAGE_VALID
) {
2516 env
->spr
[SPR_440_MMUCR
] &= ~0x000000FF;
2517 env
->spr
[SPR_440_MMUCR
] |= tlb
->PID
;
2523 ret
= tlb
->attr
& ~0x1;
2524 if (tlb
->prot
& (PAGE_READ
<< 4)) {
2527 if (tlb
->prot
& (PAGE_WRITE
<< 4)) {
2530 if (tlb
->prot
& (PAGE_EXEC
<< 4)) {
2533 if (tlb
->prot
& PAGE_READ
) {
2536 if (tlb
->prot
& PAGE_WRITE
) {
2539 if (tlb
->prot
& PAGE_EXEC
) {
2547 target_ulong
helper_440_tlbsx(CPUPPCState
*env
, target_ulong address
)
2549 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_440_MMUCR
] & 0xFF);
2552 /* PowerPC BookE 2.06 TLB management */
2554 static ppcmas_tlb_t
*booke206_cur_tlb(CPUPPCState
*env
)
2556 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2557 uint32_t tlbncfg
= 0;
2558 int esel
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ESEL_MASK
) >> MAS0_ESEL_SHIFT
;
2559 int ea
= (env
->spr
[SPR_BOOKE_MAS2
] & MAS2_EPN_MASK
);
2562 tlb
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2563 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlb
];
2565 if ((tlbncfg
& TLBnCFG_HES
) && (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_HES
)) {
2566 cpu_abort(CPU(cpu
), "we don't support HES yet\n");
2569 return booke206_get_tlbm(env
, tlb
, ea
, esel
);
2572 void helper_booke_setpid(CPUPPCState
*env
, uint32_t pidn
, target_ulong pid
)
2574 env
->spr
[pidn
] = pid
;
2575 /* changing PIDs mean we're in a different address space now */
2579 void helper_booke206_tlbwe(CPUPPCState
*env
)
2581 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2582 uint32_t tlbncfg
, tlbn
;
2584 uint32_t size_tlb
, size_ps
;
2588 switch (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_WQ_MASK
) {
2589 case MAS0_WQ_ALWAYS
:
2590 /* good to go, write that entry */
2593 /* XXX check if reserved */
2598 case MAS0_WQ_CLR_RSRV
:
2599 /* XXX clear entry */
2602 /* no idea what to do */
2606 if (((env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ATSEL
) == MAS0_ATSEL_LRAT
) &&
2608 /* XXX we don't support direct LRAT setting yet */
2609 fprintf(stderr
, "cpu: don't support LRAT setting yet\n");
2613 tlbn
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2614 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlbn
];
2616 tlb
= booke206_cur_tlb(env
);
2619 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2620 POWERPC_EXCP_INVAL
|
2621 POWERPC_EXCP_INVAL_INVAL
);
2624 /* check that we support the targeted size */
2625 size_tlb
= (env
->spr
[SPR_BOOKE_MAS1
] & MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
2626 size_ps
= booke206_tlbnps(env
, tlbn
);
2627 if ((env
->spr
[SPR_BOOKE_MAS1
] & MAS1_VALID
) && (tlbncfg
& TLBnCFG_AVAIL
) &&
2628 !(size_ps
& (1 << size_tlb
))) {
2629 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2630 POWERPC_EXCP_INVAL
|
2631 POWERPC_EXCP_INVAL_INVAL
);
2635 cpu_abort(CPU(cpu
), "missing HV implementation\n");
2637 tlb
->mas7_3
= ((uint64_t)env
->spr
[SPR_BOOKE_MAS7
] << 32) |
2638 env
->spr
[SPR_BOOKE_MAS3
];
2639 tlb
->mas1
= env
->spr
[SPR_BOOKE_MAS1
];
2642 if (!(tlbncfg
& TLBnCFG_AVAIL
)) {
2643 /* force !AVAIL TLB entries to correct page size */
2644 tlb
->mas1
&= ~MAS1_TSIZE_MASK
;
2645 /* XXX can be configured in MMUCSR0 */
2646 tlb
->mas1
|= (tlbncfg
& TLBnCFG_MINSIZE
) >> 12;
2649 /* Make a mask from TLB size to discard invalid bits in EPN field */
2650 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2651 /* Add a mask for page attributes */
2652 mask
|= MAS2_ACM
| MAS2_VLE
| MAS2_W
| MAS2_I
| MAS2_M
| MAS2_G
| MAS2_E
;
2655 /* Executing a tlbwe instruction in 32-bit mode will set
2656 * bits 0:31 of the TLB EPN field to zero.
2661 tlb
->mas2
= env
->spr
[SPR_BOOKE_MAS2
] & mask
;
2663 if (!(tlbncfg
& TLBnCFG_IPROT
)) {
2664 /* no IPROT supported by TLB */
2665 tlb
->mas1
&= ~MAS1_IPROT
;
2668 if (booke206_tlb_to_page_size(env
, tlb
) == TARGET_PAGE_SIZE
) {
2669 tlb_flush_page(env
, tlb
->mas2
& MAS2_EPN_MASK
);
2675 static inline void booke206_tlb_to_mas(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2677 int tlbn
= booke206_tlbm_to_tlbn(env
, tlb
);
2678 int way
= booke206_tlbm_to_way(env
, tlb
);
2680 env
->spr
[SPR_BOOKE_MAS0
] = tlbn
<< MAS0_TLBSEL_SHIFT
;
2681 env
->spr
[SPR_BOOKE_MAS0
] |= way
<< MAS0_ESEL_SHIFT
;
2682 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2684 env
->spr
[SPR_BOOKE_MAS1
] = tlb
->mas1
;
2685 env
->spr
[SPR_BOOKE_MAS2
] = tlb
->mas2
;
2686 env
->spr
[SPR_BOOKE_MAS3
] = tlb
->mas7_3
;
2687 env
->spr
[SPR_BOOKE_MAS7
] = tlb
->mas7_3
>> 32;
2690 void helper_booke206_tlbre(CPUPPCState
*env
)
2692 ppcmas_tlb_t
*tlb
= NULL
;
2694 tlb
= booke206_cur_tlb(env
);
2696 env
->spr
[SPR_BOOKE_MAS1
] = 0;
2698 booke206_tlb_to_mas(env
, tlb
);
2702 void helper_booke206_tlbsx(CPUPPCState
*env
, target_ulong address
)
2704 ppcmas_tlb_t
*tlb
= NULL
;
2709 spid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID_MASK
) >> MAS6_SPID_SHIFT
;
2710 sas
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
;
2712 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2713 int ways
= booke206_tlb_ways(env
, i
);
2715 for (j
= 0; j
< ways
; j
++) {
2716 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2722 if (ppcmas_tlb_check(env
, tlb
, &raddr
, address
, spid
)) {
2726 if (sas
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
2730 booke206_tlb_to_mas(env
, tlb
);
2735 /* no entry found, fill with defaults */
2736 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
2737 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
2738 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
2739 env
->spr
[SPR_BOOKE_MAS3
] = 0;
2740 env
->spr
[SPR_BOOKE_MAS7
] = 0;
2742 if (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
) {
2743 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
2746 env
->spr
[SPR_BOOKE_MAS1
] |= (env
->spr
[SPR_BOOKE_MAS6
] >> 16)
2749 /* next victim logic */
2750 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
2752 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
2753 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2756 static inline void booke206_invalidate_ea_tlb(CPUPPCState
*env
, int tlbn
,
2760 int ways
= booke206_tlb_ways(env
, tlbn
);
2763 for (i
= 0; i
< ways
; i
++) {
2764 ppcmas_tlb_t
*tlb
= booke206_get_tlbm(env
, tlbn
, ea
, i
);
2768 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2769 if (((tlb
->mas2
& MAS2_EPN_MASK
) == (ea
& mask
)) &&
2770 !(tlb
->mas1
& MAS1_IPROT
)) {
2771 tlb
->mas1
&= ~MAS1_VALID
;
2776 void helper_booke206_tlbivax(CPUPPCState
*env
, target_ulong address
)
2778 if (address
& 0x4) {
2779 /* flush all entries */
2780 if (address
& 0x8) {
2781 /* flush all of TLB1 */
2782 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB1
, 1);
2784 /* flush all of TLB0 */
2785 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB0
, 0);
2790 if (address
& 0x8) {
2791 /* flush TLB1 entries */
2792 booke206_invalidate_ea_tlb(env
, 1, address
);
2795 /* flush TLB0 entries */
2796 booke206_invalidate_ea_tlb(env
, 0, address
);
2797 tlb_flush_page(env
, address
& MAS2_EPN_MASK
);
2801 void helper_booke206_tlbilx0(CPUPPCState
*env
, target_ulong address
)
2803 /* XXX missing LPID handling */
2804 booke206_flush_tlb(env
, -1, 1);
2807 void helper_booke206_tlbilx1(CPUPPCState
*env
, target_ulong address
)
2810 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2811 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
2814 /* XXX missing LPID handling */
2815 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2816 tlb_size
= booke206_tlb_size(env
, i
);
2817 for (j
= 0; j
< tlb_size
; j
++) {
2818 if (!(tlb
[j
].mas1
& MAS1_IPROT
) &&
2819 ((tlb
[j
].mas1
& MAS1_TID_MASK
) == tid
)) {
2820 tlb
[j
].mas1
&= ~MAS1_VALID
;
2823 tlb
+= booke206_tlb_size(env
, i
);
2828 void helper_booke206_tlbilx3(CPUPPCState
*env
, target_ulong address
)
2832 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2833 int pid
= tid
>> MAS6_SPID_SHIFT
;
2834 int sgs
= env
->spr
[SPR_BOOKE_MAS5
] & MAS5_SGS
;
2835 int ind
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SIND
) ? MAS1_IND
: 0;
2836 /* XXX check for unsupported isize and raise an invalid opcode then */
2837 int size
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_ISIZE_MASK
;
2838 /* XXX implement MAV2 handling */
2841 /* XXX missing LPID handling */
2842 /* flush by pid and ea */
2843 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2844 int ways
= booke206_tlb_ways(env
, i
);
2846 for (j
= 0; j
< ways
; j
++) {
2847 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2851 if ((ppcmas_tlb_check(env
, tlb
, NULL
, address
, pid
) != 0) ||
2852 (tlb
->mas1
& MAS1_IPROT
) ||
2853 ((tlb
->mas1
& MAS1_IND
) != ind
) ||
2854 ((tlb
->mas8
& MAS8_TGS
) != sgs
)) {
2857 if (mav2
&& ((tlb
->mas1
& MAS1_TSIZE_MASK
) != size
)) {
2858 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2861 /* XXX e500mc doesn't match SAS, but other cores might */
2862 tlb
->mas1
&= ~MAS1_VALID
;
2868 void helper_booke206_tlbflush(CPUPPCState
*env
, uint32_t type
)
2873 flags
|= BOOKE206_FLUSH_TLB1
;
2877 flags
|= BOOKE206_FLUSH_TLB0
;
2880 booke206_flush_tlb(env
, flags
, 1);
2884 /*****************************************************************************/
2886 #include "exec/softmmu_exec.h"
2888 #define MMUSUFFIX _mmu
2891 #include "exec/softmmu_template.h"
2894 #include "exec/softmmu_template.h"
2897 #include "exec/softmmu_template.h"
2900 #include "exec/softmmu_template.h"
2902 /* try to fill the TLB and return an exception if error. If retaddr is
2903 NULL, it means that the function was called in C code (i.e. not
2904 from generated code or from helper.c) */
2905 /* XXX: fix it to restore all registers */
2906 void tlb_fill(CPUState
*cs
, target_ulong addr
, int is_write
, int mmu_idx
,
2909 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
2910 PowerPCCPUClass
*pcc
= POWERPC_CPU_GET_CLASS(cs
);
2911 CPUPPCState
*env
= &cpu
->env
;
2914 if (pcc
->handle_mmu_fault
) {
2915 ret
= pcc
->handle_mmu_fault(cpu
, addr
, is_write
, mmu_idx
);
2917 ret
= cpu_ppc_handle_mmu_fault(env
, addr
, is_write
, mmu_idx
);
2919 if (unlikely(ret
!= 0)) {
2920 if (likely(retaddr
)) {
2921 /* now we have a real cpu fault */
2922 cpu_restore_state(cs
, retaddr
);
2924 helper_raise_exception_err(env
, cs
->exception_index
, env
->error_code
);