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 static int pp_check(int key
, int pp
, int nx
)
98 /* Compute access rights */
105 access
|= PAGE_WRITE
;
121 access
= PAGE_READ
| PAGE_WRITE
;
132 static int check_prot(int prot
, int rw
, int access_type
)
136 if (access_type
== ACCESS_CODE
) {
137 if (prot
& PAGE_EXEC
) {
143 if (prot
& PAGE_WRITE
) {
149 if (prot
& PAGE_READ
) {
159 static inline int ppc6xx_tlb_pte_check(mmu_ctx_t
*ctx
, target_ulong pte0
,
160 target_ulong pte1
, int h
, int rw
, int type
)
162 target_ulong ptem
, mmask
;
163 int access
, ret
, pteh
, ptev
, pp
;
166 /* Check validity and table match */
167 ptev
= pte_is_valid(pte0
);
168 pteh
= (pte0
>> 6) & 1;
169 if (ptev
&& h
== pteh
) {
170 /* Check vsid & api */
171 ptem
= pte0
& PTE_PTEM_MASK
;
172 mmask
= PTE_CHECK_MASK
;
173 pp
= pte1
& 0x00000003;
174 if (ptem
== ctx
->ptem
) {
175 if (ctx
->raddr
!= (hwaddr
)-1ULL) {
176 /* all matches should have equal RPN, WIMG & PP */
177 if ((ctx
->raddr
& mmask
) != (pte1
& mmask
)) {
178 qemu_log("Bad RPN/WIMG/PP\n");
182 /* Compute access rights */
183 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
184 /* Keep the matching PTE informations */
187 ret
= check_prot(ctx
->prot
, rw
, type
);
190 LOG_MMU("PTE access granted !\n");
192 /* Access right violation */
193 LOG_MMU("PTE access rejected\n");
201 static int pte_update_flags(mmu_ctx_t
*ctx
, target_ulong
*pte1p
,
206 /* Update page flags */
207 if (!(*pte1p
& 0x00000100)) {
208 /* Update accessed flag */
209 *pte1p
|= 0x00000100;
212 if (!(*pte1p
& 0x00000080)) {
213 if (rw
== 1 && ret
== 0) {
214 /* Update changed flag */
215 *pte1p
|= 0x00000080;
218 /* Force page fault for first write access */
219 ctx
->prot
&= ~PAGE_WRITE
;
226 /* Software driven TLB helpers */
227 static inline int ppc6xx_tlb_getnum(CPUPPCState
*env
, target_ulong eaddr
,
228 int way
, int is_code
)
232 /* Select TLB num in a way from address */
233 nr
= (eaddr
>> TARGET_PAGE_BITS
) & (env
->tlb_per_way
- 1);
235 nr
+= env
->tlb_per_way
* way
;
236 /* 6xx have separate TLBs for instructions and data */
237 if (is_code
&& env
->id_tlbs
== 1) {
244 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState
*env
)
249 /* LOG_SWTLB("Invalidate all TLBs\n"); */
250 /* Invalidate all defined software TLB */
252 if (env
->id_tlbs
== 1) {
255 for (nr
= 0; nr
< max
; nr
++) {
256 tlb
= &env
->tlb
.tlb6
[nr
];
257 pte_invalidate(&tlb
->pte0
);
262 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState
*env
,
264 int is_code
, int match_epn
)
266 #if !defined(FLUSH_ALL_TLBS)
270 /* Invalidate ITLB + DTLB, all ways */
271 for (way
= 0; way
< env
->nb_ways
; way
++) {
272 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
, is_code
);
273 tlb
= &env
->tlb
.tlb6
[nr
];
274 if (pte_is_valid(tlb
->pte0
) && (match_epn
== 0 || eaddr
== tlb
->EPN
)) {
275 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx
"\n", nr
,
277 pte_invalidate(&tlb
->pte0
);
278 tlb_flush_page(env
, tlb
->EPN
);
282 /* XXX: PowerPC specification say this is valid as well */
283 ppc6xx_tlb_invalidate_all(env
);
287 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState
*env
,
288 target_ulong eaddr
, int is_code
)
290 ppc6xx_tlb_invalidate_virt2(env
, eaddr
, is_code
, 0);
293 static void ppc6xx_tlb_store(CPUPPCState
*env
, target_ulong EPN
, int way
,
294 int is_code
, target_ulong pte0
, target_ulong pte1
)
299 nr
= ppc6xx_tlb_getnum(env
, EPN
, way
, is_code
);
300 tlb
= &env
->tlb
.tlb6
[nr
];
301 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
302 " PTE1 " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
, EPN
, pte0
, pte1
);
303 /* Invalidate any pending reference in QEMU for this virtual address */
304 ppc6xx_tlb_invalidate_virt2(env
, EPN
, is_code
, 1);
308 /* Store last way for LRU mechanism */
312 static inline int ppc6xx_tlb_check(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
313 target_ulong eaddr
, int rw
, int access_type
)
320 ret
= -1; /* No TLB found */
321 for (way
= 0; way
< env
->nb_ways
; way
++) {
322 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
,
323 access_type
== ACCESS_CODE
? 1 : 0);
324 tlb
= &env
->tlb
.tlb6
[nr
];
325 /* This test "emulates" the PTE index match for hardware TLBs */
326 if ((eaddr
& TARGET_PAGE_MASK
) != tlb
->EPN
) {
327 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx
" " TARGET_FMT_lx
328 "] <> " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
,
329 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
330 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
, eaddr
);
333 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx
" <> " TARGET_FMT_lx
" "
334 TARGET_FMT_lx
" %c %c\n", nr
, env
->nb_tlb
,
335 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
336 tlb
->EPN
, eaddr
, tlb
->pte1
,
337 rw
? 'S' : 'L', access_type
== ACCESS_CODE
? 'I' : 'D');
338 switch (ppc6xx_tlb_pte_check(ctx
, tlb
->pte0
, tlb
->pte1
, 0, rw
, access_type
)) {
340 /* TLB inconsistency */
343 /* Access violation */
353 /* XXX: we should go on looping to check all TLBs consistency
354 * but we can speed-up the whole thing as the
355 * result would be undefined if TLBs are not consistent.
364 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx
" prot=%01x ret=%d\n",
365 ctx
->raddr
& TARGET_PAGE_MASK
, ctx
->prot
, ret
);
366 /* Update page flags */
367 pte_update_flags(ctx
, &env
->tlb
.tlb6
[best
].pte1
, ret
, rw
);
373 /* Perform BAT hit & translation */
374 static inline void bat_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
375 int *validp
, int *protp
, target_ulong
*BATu
,
381 bl
= (*BATu
& 0x00001FFC) << 15;
384 if (((msr_pr
== 0) && (*BATu
& 0x00000002)) ||
385 ((msr_pr
!= 0) && (*BATu
& 0x00000001))) {
387 pp
= *BATl
& 0x00000003;
389 prot
= PAGE_READ
| PAGE_EXEC
;
400 static inline void bat_601_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
401 int *validp
, int *protp
,
402 target_ulong
*BATu
, target_ulong
*BATl
)
405 int key
, pp
, valid
, prot
;
407 bl
= (*BATl
& 0x0000003F) << 17;
408 LOG_BATS("b %02x ==> bl " TARGET_FMT_lx
" msk " TARGET_FMT_lx
"\n",
409 (uint8_t)(*BATl
& 0x0000003F), bl
, ~bl
);
411 valid
= (*BATl
>> 6) & 1;
413 pp
= *BATu
& 0x00000003;
415 key
= (*BATu
>> 3) & 1;
417 key
= (*BATu
>> 2) & 1;
419 prot
= pp_check(key
, pp
, 0);
426 int get_bat(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
427 target_ulong
virtual, int rw
, int type
)
429 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
430 target_ulong BEPIl
, BEPIu
, bl
;
434 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx
"\n", __func__
,
435 type
== ACCESS_CODE
? 'I' : 'D', virtual);
438 BATlt
= env
->IBAT
[1];
439 BATut
= env
->IBAT
[0];
442 BATlt
= env
->DBAT
[1];
443 BATut
= env
->DBAT
[0];
446 for (i
= 0; i
< env
->nb_BATs
; i
++) {
449 BEPIu
= *BATu
& 0xF0000000;
450 BEPIl
= *BATu
& 0x0FFE0000;
451 if (unlikely(env
->mmu_model
== POWERPC_MMU_601
)) {
452 bat_601_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
454 bat_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
456 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
457 " BATl " TARGET_FMT_lx
"\n", __func__
,
458 type
== ACCESS_CODE
? 'I' : 'D', i
, virtual, *BATu
, *BATl
);
459 if ((virtual & 0xF0000000) == BEPIu
&&
460 ((virtual & 0x0FFE0000) & ~bl
) == BEPIl
) {
463 /* Get physical address */
464 ctx
->raddr
= (*BATl
& 0xF0000000) |
465 ((virtual & 0x0FFE0000 & bl
) | (*BATl
& 0x0FFE0000)) |
466 (virtual & 0x0001F000);
467 /* Compute access rights */
469 ret
= check_prot(ctx
->prot
, rw
, type
);
471 LOG_BATS("BAT %d match: r " TARGET_FMT_plx
" prot=%c%c\n",
472 i
, ctx
->raddr
, ctx
->prot
& PAGE_READ
? 'R' : '-',
473 ctx
->prot
& PAGE_WRITE
? 'W' : '-');
480 #if defined(DEBUG_BATS)
481 if (qemu_log_enabled()) {
482 LOG_BATS("no BAT match for " TARGET_FMT_lx
":\n", virtual);
483 for (i
= 0; i
< 4; i
++) {
486 BEPIu
= *BATu
& 0xF0000000;
487 BEPIl
= *BATu
& 0x0FFE0000;
488 bl
= (*BATu
& 0x00001FFC) << 15;
489 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
490 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
491 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
492 __func__
, type
== ACCESS_CODE
? 'I' : 'D', i
, virtual,
493 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
502 /* Perform segment based translation */
503 static inline int get_segment_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
504 target_ulong eaddr
, int rw
, int type
)
508 int ds
, pr
, target_page_bits
;
510 target_ulong sr
, pgidx
;
515 sr
= env
->sr
[eaddr
>> 28];
516 ctx
->key
= (((sr
& 0x20000000) && (pr
!= 0)) ||
517 ((sr
& 0x40000000) && (pr
== 0))) ? 1 : 0;
518 ds
= sr
& 0x80000000 ? 1 : 0;
519 ctx
->nx
= sr
& 0x10000000 ? 1 : 0;
520 vsid
= sr
& 0x00FFFFFF;
521 target_page_bits
= TARGET_PAGE_BITS
;
522 LOG_MMU("Check segment v=" TARGET_FMT_lx
" %d " TARGET_FMT_lx
" nip="
523 TARGET_FMT_lx
" lr=" TARGET_FMT_lx
524 " ir=%d dr=%d pr=%d %d t=%d\n",
525 eaddr
, (int)(eaddr
>> 28), sr
, env
->nip
, env
->lr
, (int)msr_ir
,
526 (int)msr_dr
, pr
!= 0 ? 1 : 0, rw
, type
);
527 pgidx
= (eaddr
& ~SEGMENT_MASK_256M
) >> target_page_bits
;
529 ctx
->ptem
= (vsid
<< 7) | (pgidx
>> 10);
531 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx
"\n",
532 ctx
->key
, ds
, ctx
->nx
, vsid
);
535 /* Check if instruction fetch is allowed, if needed */
536 if (type
!= ACCESS_CODE
|| ctx
->nx
== 0) {
537 /* Page address translation */
538 LOG_MMU("htab_base " TARGET_FMT_plx
" htab_mask " TARGET_FMT_plx
539 " hash " TARGET_FMT_plx
"\n",
540 env
->htab_base
, env
->htab_mask
, hash
);
542 ctx
->hash
[1] = ~hash
;
544 /* Initialize real address with an invalid value */
545 ctx
->raddr
= (hwaddr
)-1ULL;
546 /* Software TLB search */
547 ret
= ppc6xx_tlb_check(env
, ctx
, eaddr
, rw
, type
);
548 #if defined(DUMP_PAGE_TABLES)
549 if (qemu_log_enabled()) {
551 uint32_t a0
, a1
, a2
, a3
;
553 qemu_log("Page table: " TARGET_FMT_plx
" len " TARGET_FMT_plx
554 "\n", sdr
, mask
+ 0x80);
555 for (curaddr
= sdr
; curaddr
< (sdr
+ mask
+ 0x80);
557 a0
= ldl_phys(curaddr
);
558 a1
= ldl_phys(curaddr
+ 4);
559 a2
= ldl_phys(curaddr
+ 8);
560 a3
= ldl_phys(curaddr
+ 12);
561 if (a0
!= 0 || a1
!= 0 || a2
!= 0 || a3
!= 0) {
562 qemu_log(TARGET_FMT_plx
": %08x %08x %08x %08x\n",
563 curaddr
, a0
, a1
, a2
, a3
);
569 LOG_MMU("No access allowed\n");
575 LOG_MMU("direct store...\n");
576 /* Direct-store segment : absolutely *BUGGY* for now */
578 /* Direct-store implies a 32-bit MMU.
579 * Check the Segment Register's bus unit ID (BUID).
581 sr
= env
->sr
[eaddr
>> 28];
582 if ((sr
& 0x1FF00000) >> 20 == 0x07f) {
583 /* Memory-forced I/O controller interface access */
584 /* If T=1 and BUID=x'07F', the 601 performs a memory access
585 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
587 ctx
->raddr
= ((sr
& 0xF) << 28) | (eaddr
& 0x0FFFFFFF);
588 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
594 /* Integer load/store : only access allowed */
597 /* No code fetch is allowed in direct-store areas */
600 /* Floating point load/store */
603 /* lwarx, ldarx or srwcx. */
606 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
607 /* Should make the instruction do no-op.
608 * As it already do no-op, it's quite easy :-)
616 qemu_log("ERROR: instruction should not need "
617 "address translation\n");
620 if ((rw
== 1 || ctx
->key
!= 1) && (rw
== 0 || ctx
->key
!= 0)) {
631 /* Generic TLB check function for embedded PowerPC implementations */
632 static int ppcemb_tlb_check(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
634 target_ulong address
, uint32_t pid
, int ext
,
639 /* Check valid flag */
640 if (!(tlb
->prot
& PAGE_VALID
)) {
643 mask
= ~(tlb
->size
- 1);
644 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx
" PID %u <=> " TARGET_FMT_lx
645 " " TARGET_FMT_lx
" %u %x\n", __func__
, i
, address
, pid
, tlb
->EPN
,
646 mask
, (uint32_t)tlb
->PID
, tlb
->prot
);
648 if (tlb
->PID
!= 0 && tlb
->PID
!= pid
) {
651 /* Check effective address */
652 if ((address
& mask
) != tlb
->EPN
) {
655 *raddrp
= (tlb
->RPN
& mask
) | (address
& ~mask
);
657 /* Extend the physical address to 36 bits */
658 *raddrp
|= (uint64_t)(tlb
->RPN
& 0xF) << 32;
664 /* Generic TLB search function for PowerPC embedded implementations */
665 static int ppcemb_tlb_search(CPUPPCState
*env
, target_ulong address
,
672 /* Default return value is no match */
674 for (i
= 0; i
< env
->nb_tlb
; i
++) {
675 tlb
= &env
->tlb
.tlbe
[i
];
676 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
, pid
, 0, i
) == 0) {
685 /* Helpers specific to PowerPC 40x implementations */
686 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState
*env
)
691 for (i
= 0; i
< env
->nb_tlb
; i
++) {
692 tlb
= &env
->tlb
.tlbe
[i
];
693 tlb
->prot
&= ~PAGE_VALID
;
698 static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState
*env
,
699 target_ulong eaddr
, uint32_t pid
)
701 #if !defined(FLUSH_ALL_TLBS)
704 target_ulong page
, end
;
707 for (i
= 0; i
< env
->nb_tlb
; i
++) {
708 tlb
= &env
->tlb
.tlbe
[i
];
709 if (ppcemb_tlb_check(env
, tlb
, &raddr
, eaddr
, pid
, 0, i
) == 0) {
710 end
= tlb
->EPN
+ tlb
->size
;
711 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
712 tlb_flush_page(env
, page
);
714 tlb
->prot
&= ~PAGE_VALID
;
719 ppc4xx_tlb_invalidate_all(env
);
723 static int mmu40x_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
724 target_ulong address
, int rw
,
729 int i
, ret
, zsel
, zpr
, pr
;
732 raddr
= (hwaddr
)-1ULL;
734 for (i
= 0; i
< env
->nb_tlb
; i
++) {
735 tlb
= &env
->tlb
.tlbe
[i
];
736 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
737 env
->spr
[SPR_40x_PID
], 0, i
) < 0) {
740 zsel
= (tlb
->attr
>> 4) & 0xF;
741 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (30 - (2 * zsel
))) & 0x3;
742 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
743 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
744 /* Check execute enable bit */
752 /* All accesses granted */
753 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
758 /* Raise Zone protection fault. */
759 env
->spr
[SPR_40x_ESR
] = 1 << 22;
767 /* Check from TLB entry */
768 ctx
->prot
= tlb
->prot
;
769 ret
= check_prot(ctx
->prot
, rw
, access_type
);
771 env
->spr
[SPR_40x_ESR
] = 0;
777 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
778 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
783 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
784 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
789 void store_40x_sler(CPUPPCState
*env
, uint32_t val
)
791 /* XXX: TO BE FIXED */
792 if (val
!= 0x00000000) {
793 cpu_abort(env
, "Little-endian regions are not supported by now\n");
795 env
->spr
[SPR_405_SLER
] = val
;
798 static inline int mmubooke_check_tlb(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
799 hwaddr
*raddr
, int *prot
,
800 target_ulong address
, int rw
,
801 int access_type
, int i
)
805 if (ppcemb_tlb_check(env
, tlb
, raddr
, address
,
806 env
->spr
[SPR_BOOKE_PID
],
807 !env
->nb_pids
, i
) >= 0) {
811 if (env
->spr
[SPR_BOOKE_PID1
] &&
812 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
813 env
->spr
[SPR_BOOKE_PID1
], 0, i
) >= 0) {
817 if (env
->spr
[SPR_BOOKE_PID2
] &&
818 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
819 env
->spr
[SPR_BOOKE_PID2
], 0, i
) >= 0) {
823 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
829 prot2
= tlb
->prot
& 0xF;
831 prot2
= (tlb
->prot
>> 4) & 0xF;
834 /* Check the address space */
835 if (access_type
== ACCESS_CODE
) {
836 if (msr_ir
!= (tlb
->attr
& 1)) {
837 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
842 if (prot2
& PAGE_EXEC
) {
843 LOG_SWTLB("%s: good TLB!\n", __func__
);
847 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
850 if (msr_dr
!= (tlb
->attr
& 1)) {
851 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
856 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
857 LOG_SWTLB("%s: found TLB!\n", __func__
);
861 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
868 static int mmubooke_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
869 target_ulong address
, int rw
,
877 raddr
= (hwaddr
)-1ULL;
878 for (i
= 0; i
< env
->nb_tlb
; i
++) {
879 tlb
= &env
->tlb
.tlbe
[i
];
880 ret
= mmubooke_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
, rw
,
889 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
890 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
893 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
894 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
900 static void booke206_flush_tlb(CPUPPCState
*env
, int flags
,
901 const int check_iprot
)
905 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
907 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
908 if (flags
& (1 << i
)) {
909 tlb_size
= booke206_tlb_size(env
, i
);
910 for (j
= 0; j
< tlb_size
; j
++) {
911 if (!check_iprot
|| !(tlb
[j
].mas1
& MAS1_IPROT
)) {
912 tlb
[j
].mas1
&= ~MAS1_VALID
;
916 tlb
+= booke206_tlb_size(env
, i
);
922 static hwaddr
booke206_tlb_to_page_size(CPUPPCState
*env
,
927 tlbm_size
= (tlb
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
929 return 1024ULL << tlbm_size
;
932 /* TLB check function for MAS based SoftTLBs */
933 static int ppcmas_tlb_check(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
935 target_ulong address
, uint32_t pid
)
940 /* Check valid flag */
941 if (!(tlb
->mas1
& MAS1_VALID
)) {
945 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
946 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx
" PID=0x%x MAS1=0x%x MAS2=0x%"
947 PRIx64
" mask=0x" TARGET_FMT_lx
" MAS7_3=0x%" PRIx64
" MAS8=%x\n",
948 __func__
, address
, pid
, tlb
->mas1
, tlb
->mas2
, mask
, tlb
->mas7_3
,
952 tlb_pid
= (tlb
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
;
953 if (tlb_pid
!= 0 && tlb_pid
!= pid
) {
957 /* Check effective address */
958 if ((address
& mask
) != (tlb
->mas2
& MAS2_EPN_MASK
)) {
963 *raddrp
= (tlb
->mas7_3
& mask
) | (address
& ~mask
);
969 static int mmubooke206_check_tlb(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
970 hwaddr
*raddr
, int *prot
,
971 target_ulong address
, int rw
,
977 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
,
978 env
->spr
[SPR_BOOKE_PID
]) >= 0) {
982 if (env
->spr
[SPR_BOOKE_PID1
] &&
983 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
984 env
->spr
[SPR_BOOKE_PID1
]) >= 0) {
988 if (env
->spr
[SPR_BOOKE_PID2
] &&
989 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
990 env
->spr
[SPR_BOOKE_PID2
]) >= 0) {
994 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
1000 if (tlb
->mas7_3
& MAS3_UR
) {
1003 if (tlb
->mas7_3
& MAS3_UW
) {
1004 prot2
|= PAGE_WRITE
;
1006 if (tlb
->mas7_3
& MAS3_UX
) {
1010 if (tlb
->mas7_3
& MAS3_SR
) {
1013 if (tlb
->mas7_3
& MAS3_SW
) {
1014 prot2
|= PAGE_WRITE
;
1016 if (tlb
->mas7_3
& MAS3_SX
) {
1021 /* Check the address space and permissions */
1022 if (access_type
== ACCESS_CODE
) {
1023 if (msr_ir
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1024 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1029 if (prot2
& PAGE_EXEC
) {
1030 LOG_SWTLB("%s: good TLB!\n", __func__
);
1034 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
1037 if (msr_dr
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1038 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1043 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
1044 LOG_SWTLB("%s: found TLB!\n", __func__
);
1048 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
1055 static int mmubooke206_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1056 target_ulong address
, int rw
,
1064 raddr
= (hwaddr
)-1ULL;
1066 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1067 int ways
= booke206_tlb_ways(env
, i
);
1069 for (j
= 0; j
< ways
; j
++) {
1070 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
1074 ret
= mmubooke206_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
,
1086 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
1087 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1090 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
1091 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
1097 static const char *book3e_tsize_to_str
[32] = {
1098 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1099 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1100 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1104 static void mmubooke_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1107 ppcemb_tlb_t
*entry
;
1110 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1111 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1115 cpu_fprintf(f
, "\nTLB:\n");
1116 cpu_fprintf(f
, "Effective Physical Size PID Prot "
1119 entry
= &env
->tlb
.tlbe
[0];
1120 for (i
= 0; i
< env
->nb_tlb
; i
++, entry
++) {
1123 uint64_t size
= (uint64_t)entry
->size
;
1126 /* Check valid flag */
1127 if (!(entry
->prot
& PAGE_VALID
)) {
1131 mask
= ~(entry
->size
- 1);
1132 ea
= entry
->EPN
& mask
;
1133 pa
= entry
->RPN
& mask
;
1134 /* Extend the physical address to 36 bits */
1135 pa
|= (hwaddr
)(entry
->RPN
& 0xF) << 32;
1138 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"M", size
/ 1024);
1140 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"k", size
);
1142 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %s %-5u %08x %08x\n",
1143 (uint64_t)ea
, (uint64_t)pa
, size_buf
, (uint32_t)entry
->PID
,
1144 entry
->prot
, entry
->attr
);
1149 static void mmubooke206_dump_one_tlb(FILE *f
, fprintf_function cpu_fprintf
,
1150 CPUPPCState
*env
, int tlbn
, int offset
,
1153 ppcmas_tlb_t
*entry
;
1156 cpu_fprintf(f
, "\nTLB%d:\n", tlbn
);
1157 cpu_fprintf(f
, "Effective Physical Size TID TS SRWX"
1158 " URWX WIMGE U0123\n");
1160 entry
= &env
->tlb
.tlbm
[offset
];
1161 for (i
= 0; i
< tlbsize
; i
++, entry
++) {
1162 hwaddr ea
, pa
, size
;
1165 if (!(entry
->mas1
& MAS1_VALID
)) {
1169 tsize
= (entry
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1170 size
= 1024ULL << tsize
;
1171 ea
= entry
->mas2
& ~(size
- 1);
1172 pa
= entry
->mas7_3
& ~(size
- 1);
1174 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %4s %-5u %1u S%c%c%c"
1175 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1176 (uint64_t)ea
, (uint64_t)pa
,
1177 book3e_tsize_to_str
[tsize
],
1178 (entry
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
,
1179 (entry
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
,
1180 entry
->mas7_3
& MAS3_SR
? 'R' : '-',
1181 entry
->mas7_3
& MAS3_SW
? 'W' : '-',
1182 entry
->mas7_3
& MAS3_SX
? 'X' : '-',
1183 entry
->mas7_3
& MAS3_UR
? 'R' : '-',
1184 entry
->mas7_3
& MAS3_UW
? 'W' : '-',
1185 entry
->mas7_3
& MAS3_UX
? 'X' : '-',
1186 entry
->mas2
& MAS2_W
? 'W' : '-',
1187 entry
->mas2
& MAS2_I
? 'I' : '-',
1188 entry
->mas2
& MAS2_M
? 'M' : '-',
1189 entry
->mas2
& MAS2_G
? 'G' : '-',
1190 entry
->mas2
& MAS2_E
? 'E' : '-',
1191 entry
->mas7_3
& MAS3_U0
? '0' : '-',
1192 entry
->mas7_3
& MAS3_U1
? '1' : '-',
1193 entry
->mas7_3
& MAS3_U2
? '2' : '-',
1194 entry
->mas7_3
& MAS3_U3
? '3' : '-');
1198 static void mmubooke206_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1204 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1205 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1209 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1210 int size
= booke206_tlb_size(env
, i
);
1216 mmubooke206_dump_one_tlb(f
, cpu_fprintf
, env
, i
, offset
, size
);
1221 void dump_mmu(FILE *f
, fprintf_function cpu_fprintf
, CPUPPCState
*env
)
1223 switch (env
->mmu_model
) {
1224 case POWERPC_MMU_BOOKE
:
1225 mmubooke_dump_mmu(f
, cpu_fprintf
, env
);
1227 case POWERPC_MMU_BOOKE206
:
1228 mmubooke206_dump_mmu(f
, cpu_fprintf
, env
);
1230 #if defined(TARGET_PPC64)
1231 case POWERPC_MMU_64B
:
1232 case POWERPC_MMU_2_06
:
1233 case POWERPC_MMU_2_06d
:
1234 dump_slb(f
, cpu_fprintf
, env
);
1238 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented\n", __func__
);
1242 static inline int check_physical(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1243 target_ulong eaddr
, int rw
)
1248 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1250 switch (env
->mmu_model
) {
1251 case POWERPC_MMU_SOFT_6xx
:
1252 case POWERPC_MMU_SOFT_74xx
:
1253 case POWERPC_MMU_SOFT_4xx
:
1254 case POWERPC_MMU_REAL
:
1255 case POWERPC_MMU_BOOKE
:
1256 ctx
->prot
|= PAGE_WRITE
;
1259 case POWERPC_MMU_SOFT_4xx_Z
:
1260 if (unlikely(msr_pe
!= 0)) {
1261 /* 403 family add some particular protections,
1262 * using PBL/PBU registers for accesses with no translation.
1265 /* Check PLB validity */
1266 (env
->pb
[0] < env
->pb
[1] &&
1267 /* and address in plb area */
1268 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1269 (env
->pb
[2] < env
->pb
[3] &&
1270 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1271 if (in_plb
^ msr_px
) {
1272 /* Access in protected area */
1274 /* Access is not allowed */
1278 /* Read-write access is allowed */
1279 ctx
->prot
|= PAGE_WRITE
;
1285 /* Caller's checks mean we should never get here for other models */
1293 static int get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1294 target_ulong eaddr
, int rw
, int access_type
)
1297 bool real_mode
= (access_type
== ACCESS_CODE
&& msr_ir
== 0)
1298 || (access_type
!= ACCESS_CODE
&& msr_dr
== 0);
1301 qemu_log("%s\n", __func__
);
1304 switch (env
->mmu_model
) {
1305 case POWERPC_MMU_SOFT_6xx
:
1306 case POWERPC_MMU_SOFT_74xx
:
1308 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1310 /* Try to find a BAT */
1311 if (env
->nb_BATs
!= 0) {
1312 ret
= get_bat(env
, ctx
, eaddr
, rw
, access_type
);
1315 /* We didn't match any BAT entry or don't have BATs */
1316 ret
= get_segment_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1321 case POWERPC_MMU_SOFT_4xx
:
1322 case POWERPC_MMU_SOFT_4xx_Z
:
1324 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1326 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1330 case POWERPC_MMU_BOOKE
:
1331 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1334 case POWERPC_MMU_BOOKE206
:
1335 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1338 case POWERPC_MMU_MPC8xx
:
1340 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1342 case POWERPC_MMU_REAL
:
1344 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1346 cpu_abort(env
, "PowerPC in real mode do not do any translation\n");
1350 cpu_abort(env
, "Unknown or invalid MMU model\n");
1354 qemu_log("%s address " TARGET_FMT_lx
" => %d " TARGET_FMT_plx
"\n",
1355 __func__
, eaddr
, ret
, ctx
->raddr
);
1361 hwaddr
cpu_get_phys_page_debug(CPUPPCState
*env
, target_ulong addr
)
1365 switch (env
->mmu_model
) {
1366 #if defined(TARGET_PPC64)
1367 case POWERPC_MMU_64B
:
1368 case POWERPC_MMU_2_06
:
1369 case POWERPC_MMU_2_06d
:
1370 return ppc_hash64_get_phys_page_debug(env
, addr
);
1373 case POWERPC_MMU_32B
:
1374 case POWERPC_MMU_601
:
1375 return ppc_hash32_get_phys_page_debug(env
, addr
);
1381 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0)) {
1385 return ctx
.raddr
& TARGET_PAGE_MASK
;
1388 static void booke206_update_mas_tlb_miss(CPUPPCState
*env
, target_ulong address
,
1391 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
1392 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
1393 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
1394 env
->spr
[SPR_BOOKE_MAS3
] = 0;
1395 env
->spr
[SPR_BOOKE_MAS6
] = 0;
1396 env
->spr
[SPR_BOOKE_MAS7
] = 0;
1399 if (((rw
== 2) && msr_ir
) || ((rw
!= 2) && msr_dr
)) {
1400 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
1401 env
->spr
[SPR_BOOKE_MAS6
] |= MAS6_SAS
;
1404 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_VALID
;
1405 env
->spr
[SPR_BOOKE_MAS2
] |= address
& MAS2_EPN_MASK
;
1407 switch (env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TIDSELD_PIDZ
) {
1408 case MAS4_TIDSELD_PID0
:
1409 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID
] << MAS1_TID_SHIFT
;
1411 case MAS4_TIDSELD_PID1
:
1412 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID1
] << MAS1_TID_SHIFT
;
1414 case MAS4_TIDSELD_PID2
:
1415 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID2
] << MAS1_TID_SHIFT
;
1419 env
->spr
[SPR_BOOKE_MAS6
] |= env
->spr
[SPR_BOOKE_PID
] << 16;
1421 /* next victim logic */
1422 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
1424 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
1425 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
1428 /* Perform address translation */
1429 int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
, int rw
,
1436 switch (env
->mmu_model
) {
1437 #if defined(TARGET_PPC64)
1438 case POWERPC_MMU_64B
:
1439 case POWERPC_MMU_2_06
:
1440 case POWERPC_MMU_2_06d
:
1441 return ppc_hash64_handle_mmu_fault(env
, address
, rw
, mmu_idx
);
1444 case POWERPC_MMU_32B
:
1445 case POWERPC_MMU_601
:
1446 return ppc_hash32_handle_mmu_fault(env
, address
, rw
, mmu_idx
);
1449 ; /* Otherwise fall through to the general code below */
1455 access_type
= ACCESS_CODE
;
1458 access_type
= env
->access_type
;
1460 ret
= get_physical_address(env
, &ctx
, address
, rw
, access_type
);
1462 tlb_set_page(env
, address
& TARGET_PAGE_MASK
,
1463 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1464 mmu_idx
, TARGET_PAGE_SIZE
);
1466 } else if (ret
< 0) {
1468 if (access_type
== ACCESS_CODE
) {
1471 /* No matches in page tables or TLB */
1472 switch (env
->mmu_model
) {
1473 case POWERPC_MMU_SOFT_6xx
:
1474 env
->exception_index
= POWERPC_EXCP_IFTLB
;
1475 env
->error_code
= 1 << 18;
1476 env
->spr
[SPR_IMISS
] = address
;
1477 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1479 case POWERPC_MMU_SOFT_74xx
:
1480 env
->exception_index
= POWERPC_EXCP_IFTLB
;
1482 case POWERPC_MMU_SOFT_4xx
:
1483 case POWERPC_MMU_SOFT_4xx_Z
:
1484 env
->exception_index
= POWERPC_EXCP_ITLB
;
1485 env
->error_code
= 0;
1486 env
->spr
[SPR_40x_DEAR
] = address
;
1487 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1489 case POWERPC_MMU_BOOKE206
:
1490 booke206_update_mas_tlb_miss(env
, address
, rw
);
1492 case POWERPC_MMU_BOOKE
:
1493 env
->exception_index
= POWERPC_EXCP_ITLB
;
1494 env
->error_code
= 0;
1495 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1497 case POWERPC_MMU_MPC8xx
:
1499 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1501 case POWERPC_MMU_REAL
:
1502 cpu_abort(env
, "PowerPC in real mode should never raise "
1503 "any MMU exceptions\n");
1506 cpu_abort(env
, "Unknown or invalid MMU model\n");
1511 /* Access rights violation */
1512 env
->exception_index
= POWERPC_EXCP_ISI
;
1513 env
->error_code
= 0x08000000;
1516 /* No execute protection violation */
1517 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1518 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1519 env
->spr
[SPR_BOOKE_ESR
] = 0x00000000;
1521 env
->exception_index
= POWERPC_EXCP_ISI
;
1522 env
->error_code
= 0x10000000;
1525 /* Direct store exception */
1526 /* No code fetch is allowed in direct-store areas */
1527 env
->exception_index
= POWERPC_EXCP_ISI
;
1528 env
->error_code
= 0x10000000;
1534 /* No matches in page tables or TLB */
1535 switch (env
->mmu_model
) {
1536 case POWERPC_MMU_SOFT_6xx
:
1538 env
->exception_index
= POWERPC_EXCP_DSTLB
;
1539 env
->error_code
= 1 << 16;
1541 env
->exception_index
= POWERPC_EXCP_DLTLB
;
1542 env
->error_code
= 0;
1544 env
->spr
[SPR_DMISS
] = address
;
1545 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1547 env
->error_code
|= ctx
.key
<< 19;
1548 env
->spr
[SPR_HASH1
] = env
->htab_base
+
1549 get_pteg_offset32(env
, ctx
.hash
[0]);
1550 env
->spr
[SPR_HASH2
] = env
->htab_base
+
1551 get_pteg_offset32(env
, ctx
.hash
[1]);
1553 case POWERPC_MMU_SOFT_74xx
:
1555 env
->exception_index
= POWERPC_EXCP_DSTLB
;
1557 env
->exception_index
= POWERPC_EXCP_DLTLB
;
1560 /* Implement LRU algorithm */
1561 env
->error_code
= ctx
.key
<< 19;
1562 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1563 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1564 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1566 case POWERPC_MMU_SOFT_4xx
:
1567 case POWERPC_MMU_SOFT_4xx_Z
:
1568 env
->exception_index
= POWERPC_EXCP_DTLB
;
1569 env
->error_code
= 0;
1570 env
->spr
[SPR_40x_DEAR
] = address
;
1572 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1574 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1577 case POWERPC_MMU_MPC8xx
:
1579 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1581 case POWERPC_MMU_BOOKE206
:
1582 booke206_update_mas_tlb_miss(env
, address
, rw
);
1584 case POWERPC_MMU_BOOKE
:
1585 env
->exception_index
= POWERPC_EXCP_DTLB
;
1586 env
->error_code
= 0;
1587 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1588 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1590 case POWERPC_MMU_REAL
:
1591 cpu_abort(env
, "PowerPC in real mode should never raise "
1592 "any MMU exceptions\n");
1595 cpu_abort(env
, "Unknown or invalid MMU model\n");
1600 /* Access rights violation */
1601 env
->exception_index
= POWERPC_EXCP_DSI
;
1602 env
->error_code
= 0;
1603 if (env
->mmu_model
== POWERPC_MMU_SOFT_4xx
1604 || env
->mmu_model
== POWERPC_MMU_SOFT_4xx_Z
) {
1605 env
->spr
[SPR_40x_DEAR
] = address
;
1607 env
->spr
[SPR_40x_ESR
] |= 0x00800000;
1609 } else if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1610 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1611 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1612 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1614 env
->spr
[SPR_DAR
] = address
;
1616 env
->spr
[SPR_DSISR
] = 0x0A000000;
1618 env
->spr
[SPR_DSISR
] = 0x08000000;
1623 /* Direct store exception */
1624 switch (access_type
) {
1626 /* Floating point load/store */
1627 env
->exception_index
= POWERPC_EXCP_ALIGN
;
1628 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1629 env
->spr
[SPR_DAR
] = address
;
1632 /* lwarx, ldarx or stwcx. */
1633 env
->exception_index
= POWERPC_EXCP_DSI
;
1634 env
->error_code
= 0;
1635 env
->spr
[SPR_DAR
] = address
;
1637 env
->spr
[SPR_DSISR
] = 0x06000000;
1639 env
->spr
[SPR_DSISR
] = 0x04000000;
1643 /* eciwx or ecowx */
1644 env
->exception_index
= POWERPC_EXCP_DSI
;
1645 env
->error_code
= 0;
1646 env
->spr
[SPR_DAR
] = address
;
1648 env
->spr
[SPR_DSISR
] = 0x06100000;
1650 env
->spr
[SPR_DSISR
] = 0x04100000;
1654 printf("DSI: invalid exception (%d)\n", ret
);
1655 env
->exception_index
= POWERPC_EXCP_PROGRAM
;
1657 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1658 env
->spr
[SPR_DAR
] = address
;
1665 printf("%s: set exception to %d %02x\n", __func__
,
1666 env
->exception
, env
->error_code
);
1674 /*****************************************************************************/
1675 /* BATs management */
1676 #if !defined(FLUSH_ALL_TLBS)
1677 static inline void do_invalidate_BAT(CPUPPCState
*env
, target_ulong BATu
,
1680 target_ulong base
, end
, page
;
1682 base
= BATu
& ~0x0001FFFF;
1683 end
= base
+ mask
+ 0x00020000;
1684 LOG_BATS("Flush BAT from " TARGET_FMT_lx
" to " TARGET_FMT_lx
" ("
1685 TARGET_FMT_lx
")\n", base
, end
, mask
);
1686 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
1687 tlb_flush_page(env
, page
);
1689 LOG_BATS("Flush done\n");
1693 static inline void dump_store_bat(CPUPPCState
*env
, char ID
, int ul
, int nr
,
1696 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx
" (" TARGET_FMT_lx
")\n", ID
,
1697 nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1700 void helper_store_ibatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1704 dump_store_bat(env
, 'I', 0, nr
, value
);
1705 if (env
->IBAT
[0][nr
] != value
) {
1706 mask
= (value
<< 15) & 0x0FFE0000UL
;
1707 #if !defined(FLUSH_ALL_TLBS)
1708 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1710 /* When storing valid upper BAT, mask BEPI and BRPN
1711 * and invalidate all TLBs covered by this BAT
1713 mask
= (value
<< 15) & 0x0FFE0000UL
;
1714 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1715 (value
& ~0x0001FFFFUL
& ~mask
);
1716 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1717 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1718 #if !defined(FLUSH_ALL_TLBS)
1719 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1726 void helper_store_ibatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1728 dump_store_bat(env
, 'I', 1, nr
, value
);
1729 env
->IBAT
[1][nr
] = value
;
1732 void helper_store_dbatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1736 dump_store_bat(env
, 'D', 0, nr
, value
);
1737 if (env
->DBAT
[0][nr
] != value
) {
1738 /* When storing valid upper BAT, mask BEPI and BRPN
1739 * and invalidate all TLBs covered by this BAT
1741 mask
= (value
<< 15) & 0x0FFE0000UL
;
1742 #if !defined(FLUSH_ALL_TLBS)
1743 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1745 mask
= (value
<< 15) & 0x0FFE0000UL
;
1746 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1747 (value
& ~0x0001FFFFUL
& ~mask
);
1748 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1749 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1750 #if !defined(FLUSH_ALL_TLBS)
1751 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1758 void helper_store_dbatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1760 dump_store_bat(env
, 'D', 1, nr
, value
);
1761 env
->DBAT
[1][nr
] = value
;
1764 void helper_store_601_batu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1767 #if defined(FLUSH_ALL_TLBS)
1771 dump_store_bat(env
, 'I', 0, nr
, value
);
1772 if (env
->IBAT
[0][nr
] != value
) {
1773 #if defined(FLUSH_ALL_TLBS)
1776 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1777 if (env
->IBAT
[1][nr
] & 0x40) {
1778 /* Invalidate BAT only if it is valid */
1779 #if !defined(FLUSH_ALL_TLBS)
1780 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1785 /* When storing valid upper BAT, mask BEPI and BRPN
1786 * and invalidate all TLBs covered by this BAT
1788 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1789 (value
& ~0x0001FFFFUL
& ~mask
);
1790 env
->DBAT
[0][nr
] = env
->IBAT
[0][nr
];
1791 if (env
->IBAT
[1][nr
] & 0x40) {
1792 #if !defined(FLUSH_ALL_TLBS)
1793 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1798 #if defined(FLUSH_ALL_TLBS)
1806 void helper_store_601_batl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1808 #if !defined(FLUSH_ALL_TLBS)
1814 dump_store_bat(env
, 'I', 1, nr
, value
);
1815 if (env
->IBAT
[1][nr
] != value
) {
1816 #if defined(FLUSH_ALL_TLBS)
1819 if (env
->IBAT
[1][nr
] & 0x40) {
1820 #if !defined(FLUSH_ALL_TLBS)
1821 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1822 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1828 #if !defined(FLUSH_ALL_TLBS)
1829 mask
= (value
<< 17) & 0x0FFE0000UL
;
1830 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1835 env
->IBAT
[1][nr
] = value
;
1836 env
->DBAT
[1][nr
] = value
;
1837 #if defined(FLUSH_ALL_TLBS)
1845 /*****************************************************************************/
1846 /* TLB management */
1847 void ppc_tlb_invalidate_all(CPUPPCState
*env
)
1849 switch (env
->mmu_model
) {
1850 case POWERPC_MMU_SOFT_6xx
:
1851 case POWERPC_MMU_SOFT_74xx
:
1852 ppc6xx_tlb_invalidate_all(env
);
1854 case POWERPC_MMU_SOFT_4xx
:
1855 case POWERPC_MMU_SOFT_4xx_Z
:
1856 ppc4xx_tlb_invalidate_all(env
);
1858 case POWERPC_MMU_REAL
:
1859 cpu_abort(env
, "No TLB for PowerPC 4xx in real mode\n");
1861 case POWERPC_MMU_MPC8xx
:
1863 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1865 case POWERPC_MMU_BOOKE
:
1868 case POWERPC_MMU_BOOKE206
:
1869 booke206_flush_tlb(env
, -1, 0);
1871 case POWERPC_MMU_32B
:
1872 case POWERPC_MMU_601
:
1873 #if defined(TARGET_PPC64)
1874 case POWERPC_MMU_64B
:
1875 case POWERPC_MMU_2_06
:
1876 case POWERPC_MMU_2_06d
:
1877 #endif /* defined(TARGET_PPC64) */
1882 cpu_abort(env
, "Unknown MMU model\n");
1887 void ppc_tlb_invalidate_one(CPUPPCState
*env
, target_ulong addr
)
1889 #if !defined(FLUSH_ALL_TLBS)
1890 addr
&= TARGET_PAGE_MASK
;
1891 switch (env
->mmu_model
) {
1892 case POWERPC_MMU_SOFT_6xx
:
1893 case POWERPC_MMU_SOFT_74xx
:
1894 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
1895 if (env
->id_tlbs
== 1) {
1896 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
1899 case POWERPC_MMU_SOFT_4xx
:
1900 case POWERPC_MMU_SOFT_4xx_Z
:
1901 ppc4xx_tlb_invalidate_virt(env
, addr
, env
->spr
[SPR_40x_PID
]);
1903 case POWERPC_MMU_REAL
:
1904 cpu_abort(env
, "No TLB for PowerPC 4xx in real mode\n");
1906 case POWERPC_MMU_MPC8xx
:
1908 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1910 case POWERPC_MMU_BOOKE
:
1912 cpu_abort(env
, "BookE MMU model is not implemented\n");
1914 case POWERPC_MMU_BOOKE206
:
1916 cpu_abort(env
, "BookE 2.06 MMU model is not implemented\n");
1918 case POWERPC_MMU_32B
:
1919 case POWERPC_MMU_601
:
1920 /* tlbie invalidate TLBs for all segments */
1921 addr
&= ~((target_ulong
)-1ULL << 28);
1922 /* XXX: this case should be optimized,
1923 * giving a mask to tlb_flush_page
1925 tlb_flush_page(env
, addr
| (0x0 << 28));
1926 tlb_flush_page(env
, addr
| (0x1 << 28));
1927 tlb_flush_page(env
, addr
| (0x2 << 28));
1928 tlb_flush_page(env
, addr
| (0x3 << 28));
1929 tlb_flush_page(env
, addr
| (0x4 << 28));
1930 tlb_flush_page(env
, addr
| (0x5 << 28));
1931 tlb_flush_page(env
, addr
| (0x6 << 28));
1932 tlb_flush_page(env
, addr
| (0x7 << 28));
1933 tlb_flush_page(env
, addr
| (0x8 << 28));
1934 tlb_flush_page(env
, addr
| (0x9 << 28));
1935 tlb_flush_page(env
, addr
| (0xA << 28));
1936 tlb_flush_page(env
, addr
| (0xB << 28));
1937 tlb_flush_page(env
, addr
| (0xC << 28));
1938 tlb_flush_page(env
, addr
| (0xD << 28));
1939 tlb_flush_page(env
, addr
| (0xE << 28));
1940 tlb_flush_page(env
, addr
| (0xF << 28));
1942 #if defined(TARGET_PPC64)
1943 case POWERPC_MMU_64B
:
1944 case POWERPC_MMU_2_06
:
1945 case POWERPC_MMU_2_06d
:
1946 /* tlbie invalidate TLBs for all segments */
1947 /* XXX: given the fact that there are too many segments to invalidate,
1948 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
1949 * we just invalidate all TLBs
1953 #endif /* defined(TARGET_PPC64) */
1956 cpu_abort(env
, "Unknown MMU model\n");
1960 ppc_tlb_invalidate_all(env
);
1964 /*****************************************************************************/
1965 /* Special registers manipulation */
1966 void ppc_store_sdr1(CPUPPCState
*env
, target_ulong value
)
1968 LOG_MMU("%s: " TARGET_FMT_lx
"\n", __func__
, value
);
1969 if (env
->spr
[SPR_SDR1
] != value
) {
1970 env
->spr
[SPR_SDR1
] = value
;
1971 #if defined(TARGET_PPC64)
1972 if (env
->mmu_model
& POWERPC_MMU_64
) {
1973 target_ulong htabsize
= value
& SDR_64_HTABSIZE
;
1975 if (htabsize
> 28) {
1976 fprintf(stderr
, "Invalid HTABSIZE 0x" TARGET_FMT_lx
1977 " stored in SDR1\n", htabsize
);
1980 env
->htab_mask
= (1ULL << (htabsize
+ 18)) - 1;
1981 env
->htab_base
= value
& SDR_64_HTABORG
;
1983 #endif /* defined(TARGET_PPC64) */
1985 /* FIXME: Should check for valid HTABMASK values */
1986 env
->htab_mask
= ((value
& SDR_32_HTABMASK
) << 16) | 0xFFFF;
1987 env
->htab_base
= value
& SDR_32_HTABORG
;
1993 /* Segment registers load and store */
1994 target_ulong
helper_load_sr(CPUPPCState
*env
, target_ulong sr_num
)
1996 #if defined(TARGET_PPC64)
1997 if (env
->mmu_model
& POWERPC_MMU_64
) {
2002 return env
->sr
[sr_num
];
2005 void helper_store_sr(CPUPPCState
*env
, target_ulong srnum
, target_ulong value
)
2007 LOG_MMU("%s: reg=%d " TARGET_FMT_lx
" " TARGET_FMT_lx
"\n", __func__
,
2008 (int)srnum
, value
, env
->sr
[srnum
]);
2009 #if defined(TARGET_PPC64)
2010 if (env
->mmu_model
& POWERPC_MMU_64
) {
2011 uint64_t rb
= 0, rs
= 0;
2014 rb
|= ((uint32_t)srnum
& 0xf) << 28;
2015 /* Set the valid bit */
2018 rb
|= (uint32_t)srnum
;
2021 rs
|= (value
& 0xfffffff) << 12;
2023 rs
|= ((value
>> 27) & 0xf) << 8;
2025 ppc_store_slb(env
, rb
, rs
);
2028 if (env
->sr
[srnum
] != value
) {
2029 env
->sr
[srnum
] = value
;
2030 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2031 flusing the whole TLB. */
2032 #if !defined(FLUSH_ALL_TLBS) && 0
2034 target_ulong page
, end
;
2035 /* Invalidate 256 MB of virtual memory */
2036 page
= (16 << 20) * srnum
;
2037 end
= page
+ (16 << 20);
2038 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
2039 tlb_flush_page(env
, page
);
2047 #endif /* !defined(CONFIG_USER_ONLY) */
2049 #if !defined(CONFIG_USER_ONLY)
2050 /* TLB management */
2051 void helper_tlbia(CPUPPCState
*env
)
2053 ppc_tlb_invalidate_all(env
);
2056 void helper_tlbie(CPUPPCState
*env
, target_ulong addr
)
2058 ppc_tlb_invalidate_one(env
, addr
);
2061 /* Software driven TLBs management */
2062 /* PowerPC 602/603 software TLB load instructions helpers */
2063 static void do_6xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2065 target_ulong RPN
, CMP
, EPN
;
2068 RPN
= env
->spr
[SPR_RPA
];
2070 CMP
= env
->spr
[SPR_ICMP
];
2071 EPN
= env
->spr
[SPR_IMISS
];
2073 CMP
= env
->spr
[SPR_DCMP
];
2074 EPN
= env
->spr
[SPR_DMISS
];
2076 way
= (env
->spr
[SPR_SRR1
] >> 17) & 1;
2077 (void)EPN
; /* avoid a compiler warning */
2078 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2079 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2081 /* Store this TLB */
2082 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2083 way
, is_code
, CMP
, RPN
);
2086 void helper_6xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2088 do_6xx_tlb(env
, EPN
, 0);
2091 void helper_6xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2093 do_6xx_tlb(env
, EPN
, 1);
2096 /* PowerPC 74xx software TLB load instructions helpers */
2097 static void do_74xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2099 target_ulong RPN
, CMP
, EPN
;
2102 RPN
= env
->spr
[SPR_PTELO
];
2103 CMP
= env
->spr
[SPR_PTEHI
];
2104 EPN
= env
->spr
[SPR_TLBMISS
] & ~0x3;
2105 way
= env
->spr
[SPR_TLBMISS
] & 0x3;
2106 (void)EPN
; /* avoid a compiler warning */
2107 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2108 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2110 /* Store this TLB */
2111 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2112 way
, is_code
, CMP
, RPN
);
2115 void helper_74xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2117 do_74xx_tlb(env
, EPN
, 0);
2120 void helper_74xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2122 do_74xx_tlb(env
, EPN
, 1);
2125 /*****************************************************************************/
2126 /* PowerPC 601 specific instructions (POWER bridge) */
2128 target_ulong
helper_rac(CPUPPCState
*env
, target_ulong addr
)
2132 target_ulong ret
= 0;
2134 /* We don't have to generate many instances of this instruction,
2135 * as rac is supervisor only.
2137 /* XXX: FIX THIS: Pretend we have no BAT */
2138 nb_BATs
= env
->nb_BATs
;
2140 if (get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) == 0) {
2143 env
->nb_BATs
= nb_BATs
;
2147 static inline target_ulong
booke_tlb_to_page_size(int size
)
2149 return 1024 << (2 * size
);
2152 static inline int booke_page_size_to_tlb(target_ulong page_size
)
2156 switch (page_size
) {
2190 #if defined(TARGET_PPC64)
2191 case 0x000100000000ULL
:
2194 case 0x000400000000ULL
:
2197 case 0x001000000000ULL
:
2200 case 0x004000000000ULL
:
2203 case 0x010000000000ULL
:
2215 /* Helpers for 4xx TLB management */
2216 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2218 #define PPC4XX_TLBHI_V 0x00000040
2219 #define PPC4XX_TLBHI_E 0x00000020
2220 #define PPC4XX_TLBHI_SIZE_MIN 0
2221 #define PPC4XX_TLBHI_SIZE_MAX 7
2222 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2223 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2224 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2226 #define PPC4XX_TLBLO_EX 0x00000200
2227 #define PPC4XX_TLBLO_WR 0x00000100
2228 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2229 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2231 target_ulong
helper_4xx_tlbre_hi(CPUPPCState
*env
, target_ulong entry
)
2237 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2238 tlb
= &env
->tlb
.tlbe
[entry
];
2240 if (tlb
->prot
& PAGE_VALID
) {
2241 ret
|= PPC4XX_TLBHI_V
;
2243 size
= booke_page_size_to_tlb(tlb
->size
);
2244 if (size
< PPC4XX_TLBHI_SIZE_MIN
|| size
> PPC4XX_TLBHI_SIZE_MAX
) {
2245 size
= PPC4XX_TLBHI_SIZE_DEFAULT
;
2247 ret
|= size
<< PPC4XX_TLBHI_SIZE_SHIFT
;
2248 env
->spr
[SPR_40x_PID
] = tlb
->PID
;
2252 target_ulong
helper_4xx_tlbre_lo(CPUPPCState
*env
, target_ulong entry
)
2257 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2258 tlb
= &env
->tlb
.tlbe
[entry
];
2260 if (tlb
->prot
& PAGE_EXEC
) {
2261 ret
|= PPC4XX_TLBLO_EX
;
2263 if (tlb
->prot
& PAGE_WRITE
) {
2264 ret
|= PPC4XX_TLBLO_WR
;
2269 void helper_4xx_tlbwe_hi(CPUPPCState
*env
, target_ulong entry
,
2273 target_ulong page
, end
;
2275 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2277 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2278 tlb
= &env
->tlb
.tlbe
[entry
];
2279 /* Invalidate previous TLB (if it's valid) */
2280 if (tlb
->prot
& PAGE_VALID
) {
2281 end
= tlb
->EPN
+ tlb
->size
;
2282 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx
" end "
2283 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2284 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2285 tlb_flush_page(env
, page
);
2288 tlb
->size
= booke_tlb_to_page_size((val
>> PPC4XX_TLBHI_SIZE_SHIFT
)
2289 & PPC4XX_TLBHI_SIZE_MASK
);
2290 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2291 * If this ever occurs, one should use the ppcemb target instead
2292 * of the ppc or ppc64 one
2294 if ((val
& PPC4XX_TLBHI_V
) && tlb
->size
< TARGET_PAGE_SIZE
) {
2295 cpu_abort(env
, "TLB size " TARGET_FMT_lu
" < %u "
2296 "are not supported (%d)\n",
2297 tlb
->size
, TARGET_PAGE_SIZE
, (int)((val
>> 7) & 0x7));
2299 tlb
->EPN
= val
& ~(tlb
->size
- 1);
2300 if (val
& PPC4XX_TLBHI_V
) {
2301 tlb
->prot
|= PAGE_VALID
;
2302 if (val
& PPC4XX_TLBHI_E
) {
2303 /* XXX: TO BE FIXED */
2305 "Little-endian TLB entries are not supported by now\n");
2308 tlb
->prot
&= ~PAGE_VALID
;
2310 tlb
->PID
= env
->spr
[SPR_40x_PID
]; /* PID */
2311 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2312 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2313 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2314 tlb
->prot
& PAGE_READ
? 'r' : '-',
2315 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2316 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2317 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2318 /* Invalidate new TLB (if valid) */
2319 if (tlb
->prot
& PAGE_VALID
) {
2320 end
= tlb
->EPN
+ tlb
->size
;
2321 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx
" end "
2322 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2323 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2324 tlb_flush_page(env
, page
);
2329 void helper_4xx_tlbwe_lo(CPUPPCState
*env
, target_ulong entry
,
2334 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2336 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2337 tlb
= &env
->tlb
.tlbe
[entry
];
2338 tlb
->attr
= val
& PPC4XX_TLBLO_ATTR_MASK
;
2339 tlb
->RPN
= val
& PPC4XX_TLBLO_RPN_MASK
;
2340 tlb
->prot
= PAGE_READ
;
2341 if (val
& PPC4XX_TLBLO_EX
) {
2342 tlb
->prot
|= PAGE_EXEC
;
2344 if (val
& PPC4XX_TLBLO_WR
) {
2345 tlb
->prot
|= PAGE_WRITE
;
2347 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2348 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2349 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2350 tlb
->prot
& PAGE_READ
? 'r' : '-',
2351 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2352 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2353 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2356 target_ulong
helper_4xx_tlbsx(CPUPPCState
*env
, target_ulong address
)
2358 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_40x_PID
]);
2361 /* PowerPC 440 TLB management */
2362 void helper_440_tlbwe(CPUPPCState
*env
, uint32_t word
, target_ulong entry
,
2366 target_ulong EPN
, RPN
, size
;
2369 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx
"\n",
2370 __func__
, word
, (int)entry
, value
);
2373 tlb
= &env
->tlb
.tlbe
[entry
];
2376 /* Just here to please gcc */
2378 EPN
= value
& 0xFFFFFC00;
2379 if ((tlb
->prot
& PAGE_VALID
) && EPN
!= tlb
->EPN
) {
2383 size
= booke_tlb_to_page_size((value
>> 4) & 0xF);
2384 if ((tlb
->prot
& PAGE_VALID
) && tlb
->size
< size
) {
2389 tlb
->attr
|= (value
>> 8) & 1;
2390 if (value
& 0x200) {
2391 tlb
->prot
|= PAGE_VALID
;
2393 if (tlb
->prot
& PAGE_VALID
) {
2394 tlb
->prot
&= ~PAGE_VALID
;
2398 tlb
->PID
= env
->spr
[SPR_440_MMUCR
] & 0x000000FF;
2399 if (do_flush_tlbs
) {
2404 RPN
= value
& 0xFFFFFC0F;
2405 if ((tlb
->prot
& PAGE_VALID
) && tlb
->RPN
!= RPN
) {
2411 tlb
->attr
= (tlb
->attr
& 0x1) | (value
& 0x0000FF00);
2412 tlb
->prot
= tlb
->prot
& PAGE_VALID
;
2414 tlb
->prot
|= PAGE_READ
<< 4;
2417 tlb
->prot
|= PAGE_WRITE
<< 4;
2420 tlb
->prot
|= PAGE_EXEC
<< 4;
2423 tlb
->prot
|= PAGE_READ
;
2426 tlb
->prot
|= PAGE_WRITE
;
2429 tlb
->prot
|= PAGE_EXEC
;
2435 target_ulong
helper_440_tlbre(CPUPPCState
*env
, uint32_t word
,
2443 tlb
= &env
->tlb
.tlbe
[entry
];
2446 /* Just here to please gcc */
2449 size
= booke_page_size_to_tlb(tlb
->size
);
2450 if (size
< 0 || size
> 0xF) {
2454 if (tlb
->attr
& 0x1) {
2457 if (tlb
->prot
& PAGE_VALID
) {
2460 env
->spr
[SPR_440_MMUCR
] &= ~0x000000FF;
2461 env
->spr
[SPR_440_MMUCR
] |= tlb
->PID
;
2467 ret
= tlb
->attr
& ~0x1;
2468 if (tlb
->prot
& (PAGE_READ
<< 4)) {
2471 if (tlb
->prot
& (PAGE_WRITE
<< 4)) {
2474 if (tlb
->prot
& (PAGE_EXEC
<< 4)) {
2477 if (tlb
->prot
& PAGE_READ
) {
2480 if (tlb
->prot
& PAGE_WRITE
) {
2483 if (tlb
->prot
& PAGE_EXEC
) {
2491 target_ulong
helper_440_tlbsx(CPUPPCState
*env
, target_ulong address
)
2493 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_440_MMUCR
] & 0xFF);
2496 /* PowerPC BookE 2.06 TLB management */
2498 static ppcmas_tlb_t
*booke206_cur_tlb(CPUPPCState
*env
)
2500 uint32_t tlbncfg
= 0;
2501 int esel
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ESEL_MASK
) >> MAS0_ESEL_SHIFT
;
2502 int ea
= (env
->spr
[SPR_BOOKE_MAS2
] & MAS2_EPN_MASK
);
2505 tlb
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2506 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlb
];
2508 if ((tlbncfg
& TLBnCFG_HES
) && (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_HES
)) {
2509 cpu_abort(env
, "we don't support HES yet\n");
2512 return booke206_get_tlbm(env
, tlb
, ea
, esel
);
2515 void helper_booke_setpid(CPUPPCState
*env
, uint32_t pidn
, target_ulong pid
)
2517 env
->spr
[pidn
] = pid
;
2518 /* changing PIDs mean we're in a different address space now */
2522 void helper_booke206_tlbwe(CPUPPCState
*env
)
2524 uint32_t tlbncfg
, tlbn
;
2526 uint32_t size_tlb
, size_ps
;
2530 switch (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_WQ_MASK
) {
2531 case MAS0_WQ_ALWAYS
:
2532 /* good to go, write that entry */
2535 /* XXX check if reserved */
2540 case MAS0_WQ_CLR_RSRV
:
2541 /* XXX clear entry */
2544 /* no idea what to do */
2548 if (((env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ATSEL
) == MAS0_ATSEL_LRAT
) &&
2550 /* XXX we don't support direct LRAT setting yet */
2551 fprintf(stderr
, "cpu: don't support LRAT setting yet\n");
2555 tlbn
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2556 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlbn
];
2558 tlb
= booke206_cur_tlb(env
);
2561 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2562 POWERPC_EXCP_INVAL
|
2563 POWERPC_EXCP_INVAL_INVAL
);
2566 /* check that we support the targeted size */
2567 size_tlb
= (env
->spr
[SPR_BOOKE_MAS1
] & MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
2568 size_ps
= booke206_tlbnps(env
, tlbn
);
2569 if ((env
->spr
[SPR_BOOKE_MAS1
] & MAS1_VALID
) && (tlbncfg
& TLBnCFG_AVAIL
) &&
2570 !(size_ps
& (1 << size_tlb
))) {
2571 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2572 POWERPC_EXCP_INVAL
|
2573 POWERPC_EXCP_INVAL_INVAL
);
2577 cpu_abort(env
, "missing HV implementation\n");
2579 tlb
->mas7_3
= ((uint64_t)env
->spr
[SPR_BOOKE_MAS7
] << 32) |
2580 env
->spr
[SPR_BOOKE_MAS3
];
2581 tlb
->mas1
= env
->spr
[SPR_BOOKE_MAS1
];
2584 if (!(tlbncfg
& TLBnCFG_AVAIL
)) {
2585 /* force !AVAIL TLB entries to correct page size */
2586 tlb
->mas1
&= ~MAS1_TSIZE_MASK
;
2587 /* XXX can be configured in MMUCSR0 */
2588 tlb
->mas1
|= (tlbncfg
& TLBnCFG_MINSIZE
) >> 12;
2591 /* Make a mask from TLB size to discard invalid bits in EPN field */
2592 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2593 /* Add a mask for page attributes */
2594 mask
|= MAS2_ACM
| MAS2_VLE
| MAS2_W
| MAS2_I
| MAS2_M
| MAS2_G
| MAS2_E
;
2597 /* Executing a tlbwe instruction in 32-bit mode will set
2598 * bits 0:31 of the TLB EPN field to zero.
2603 tlb
->mas2
= env
->spr
[SPR_BOOKE_MAS2
] & mask
;
2605 if (!(tlbncfg
& TLBnCFG_IPROT
)) {
2606 /* no IPROT supported by TLB */
2607 tlb
->mas1
&= ~MAS1_IPROT
;
2610 if (booke206_tlb_to_page_size(env
, tlb
) == TARGET_PAGE_SIZE
) {
2611 tlb_flush_page(env
, tlb
->mas2
& MAS2_EPN_MASK
);
2617 static inline void booke206_tlb_to_mas(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2619 int tlbn
= booke206_tlbm_to_tlbn(env
, tlb
);
2620 int way
= booke206_tlbm_to_way(env
, tlb
);
2622 env
->spr
[SPR_BOOKE_MAS0
] = tlbn
<< MAS0_TLBSEL_SHIFT
;
2623 env
->spr
[SPR_BOOKE_MAS0
] |= way
<< MAS0_ESEL_SHIFT
;
2624 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2626 env
->spr
[SPR_BOOKE_MAS1
] = tlb
->mas1
;
2627 env
->spr
[SPR_BOOKE_MAS2
] = tlb
->mas2
;
2628 env
->spr
[SPR_BOOKE_MAS3
] = tlb
->mas7_3
;
2629 env
->spr
[SPR_BOOKE_MAS7
] = tlb
->mas7_3
>> 32;
2632 void helper_booke206_tlbre(CPUPPCState
*env
)
2634 ppcmas_tlb_t
*tlb
= NULL
;
2636 tlb
= booke206_cur_tlb(env
);
2638 env
->spr
[SPR_BOOKE_MAS1
] = 0;
2640 booke206_tlb_to_mas(env
, tlb
);
2644 void helper_booke206_tlbsx(CPUPPCState
*env
, target_ulong address
)
2646 ppcmas_tlb_t
*tlb
= NULL
;
2651 spid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID_MASK
) >> MAS6_SPID_SHIFT
;
2652 sas
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
;
2654 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2655 int ways
= booke206_tlb_ways(env
, i
);
2657 for (j
= 0; j
< ways
; j
++) {
2658 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2664 if (ppcmas_tlb_check(env
, tlb
, &raddr
, address
, spid
)) {
2668 if (sas
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
2672 booke206_tlb_to_mas(env
, tlb
);
2677 /* no entry found, fill with defaults */
2678 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
2679 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
2680 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
2681 env
->spr
[SPR_BOOKE_MAS3
] = 0;
2682 env
->spr
[SPR_BOOKE_MAS7
] = 0;
2684 if (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
) {
2685 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
2688 env
->spr
[SPR_BOOKE_MAS1
] |= (env
->spr
[SPR_BOOKE_MAS6
] >> 16)
2691 /* next victim logic */
2692 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
2694 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
2695 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2698 static inline void booke206_invalidate_ea_tlb(CPUPPCState
*env
, int tlbn
,
2702 int ways
= booke206_tlb_ways(env
, tlbn
);
2705 for (i
= 0; i
< ways
; i
++) {
2706 ppcmas_tlb_t
*tlb
= booke206_get_tlbm(env
, tlbn
, ea
, i
);
2710 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2711 if (((tlb
->mas2
& MAS2_EPN_MASK
) == (ea
& mask
)) &&
2712 !(tlb
->mas1
& MAS1_IPROT
)) {
2713 tlb
->mas1
&= ~MAS1_VALID
;
2718 void helper_booke206_tlbivax(CPUPPCState
*env
, target_ulong address
)
2720 if (address
& 0x4) {
2721 /* flush all entries */
2722 if (address
& 0x8) {
2723 /* flush all of TLB1 */
2724 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB1
, 1);
2726 /* flush all of TLB0 */
2727 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB0
, 0);
2732 if (address
& 0x8) {
2733 /* flush TLB1 entries */
2734 booke206_invalidate_ea_tlb(env
, 1, address
);
2737 /* flush TLB0 entries */
2738 booke206_invalidate_ea_tlb(env
, 0, address
);
2739 tlb_flush_page(env
, address
& MAS2_EPN_MASK
);
2743 void helper_booke206_tlbilx0(CPUPPCState
*env
, target_ulong address
)
2745 /* XXX missing LPID handling */
2746 booke206_flush_tlb(env
, -1, 1);
2749 void helper_booke206_tlbilx1(CPUPPCState
*env
, target_ulong address
)
2752 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2753 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
2756 /* XXX missing LPID handling */
2757 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2758 tlb_size
= booke206_tlb_size(env
, i
);
2759 for (j
= 0; j
< tlb_size
; j
++) {
2760 if (!(tlb
[j
].mas1
& MAS1_IPROT
) &&
2761 ((tlb
[j
].mas1
& MAS1_TID_MASK
) == tid
)) {
2762 tlb
[j
].mas1
&= ~MAS1_VALID
;
2765 tlb
+= booke206_tlb_size(env
, i
);
2770 void helper_booke206_tlbilx3(CPUPPCState
*env
, target_ulong address
)
2774 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2775 int pid
= tid
>> MAS6_SPID_SHIFT
;
2776 int sgs
= env
->spr
[SPR_BOOKE_MAS5
] & MAS5_SGS
;
2777 int ind
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SIND
) ? MAS1_IND
: 0;
2778 /* XXX check for unsupported isize and raise an invalid opcode then */
2779 int size
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_ISIZE_MASK
;
2780 /* XXX implement MAV2 handling */
2783 /* XXX missing LPID handling */
2784 /* flush by pid and ea */
2785 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2786 int ways
= booke206_tlb_ways(env
, i
);
2788 for (j
= 0; j
< ways
; j
++) {
2789 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2793 if ((ppcmas_tlb_check(env
, tlb
, NULL
, address
, pid
) != 0) ||
2794 (tlb
->mas1
& MAS1_IPROT
) ||
2795 ((tlb
->mas1
& MAS1_IND
) != ind
) ||
2796 ((tlb
->mas8
& MAS8_TGS
) != sgs
)) {
2799 if (mav2
&& ((tlb
->mas1
& MAS1_TSIZE_MASK
) != size
)) {
2800 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2803 /* XXX e500mc doesn't match SAS, but other cores might */
2804 tlb
->mas1
&= ~MAS1_VALID
;
2810 void helper_booke206_tlbflush(CPUPPCState
*env
, uint32_t type
)
2815 flags
|= BOOKE206_FLUSH_TLB1
;
2819 flags
|= BOOKE206_FLUSH_TLB0
;
2822 booke206_flush_tlb(env
, flags
, 1);