2 * PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "sysemu/kvm.h"
23 #include "mmu-hash64.h"
24 #include "mmu-hash32.h"
28 //#define DEBUG_SOFTWARE_TLB
29 //#define DUMP_PAGE_TABLES
30 //#define DEBUG_SOFTWARE_TLB
31 //#define FLUSH_ALL_TLBS
34 # define LOG_MMU(...) qemu_log(__VA_ARGS__)
35 # define LOG_MMU_STATE(env) log_cpu_state((env), 0)
37 # define LOG_MMU(...) do { } while (0)
38 # define LOG_MMU_STATE(...) do { } while (0)
41 #ifdef DEBUG_SOFTWARE_TLB
42 # define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
44 # define LOG_SWTLB(...) do { } while (0)
48 # define LOG_BATS(...) qemu_log(__VA_ARGS__)
50 # define LOG_BATS(...) do { } while (0)
53 /*****************************************************************************/
54 /* PowerPC MMU emulation */
55 #if defined(CONFIG_USER_ONLY)
56 int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
, int rw
,
59 int exception
, error_code
;
62 exception
= POWERPC_EXCP_ISI
;
63 error_code
= 0x40000000;
65 exception
= POWERPC_EXCP_DSI
;
66 error_code
= 0x40000000;
68 error_code
|= 0x02000000;
70 env
->spr
[SPR_DAR
] = address
;
71 env
->spr
[SPR_DSISR
] = error_code
;
73 env
->exception_index
= exception
;
74 env
->error_code
= error_code
;
80 /* Common routines used by software and hardware TLBs emulation */
81 static inline int pte_is_valid(target_ulong pte0
)
83 return pte0
& 0x80000000 ? 1 : 0;
86 static inline void pte_invalidate(target_ulong
*pte0
)
91 #define PTE_PTEM_MASK 0x7FFFFFBF
92 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
94 int pp_check(int key
, int pp
, int nx
)
98 /* Compute access rights */
99 /* When pp is 3/7, the result is undefined. Set it to noaccess */
106 access
|= PAGE_WRITE
;
124 access
= PAGE_READ
| PAGE_WRITE
;
135 int check_prot(int prot
, int rw
, int access_type
)
139 if (access_type
== ACCESS_CODE
) {
140 if (prot
& PAGE_EXEC
) {
146 if (prot
& PAGE_WRITE
) {
152 if (prot
& PAGE_READ
) {
162 static inline int ppc6xx_tlb_pte_check(mmu_ctx_t
*ctx
, target_ulong pte0
,
163 target_ulong pte1
, int h
, int rw
, int type
)
165 target_ulong ptem
, mmask
;
166 int access
, ret
, pteh
, ptev
, pp
;
169 /* Check validity and table match */
170 ptev
= pte_is_valid(pte0
);
171 pteh
= (pte0
>> 6) & 1;
172 if (ptev
&& h
== pteh
) {
173 /* Check vsid & api */
174 ptem
= pte0
& PTE_PTEM_MASK
;
175 mmask
= PTE_CHECK_MASK
;
176 pp
= pte1
& 0x00000003;
177 if (ptem
== ctx
->ptem
) {
178 if (ctx
->raddr
!= (hwaddr
)-1ULL) {
179 /* all matches should have equal RPN, WIMG & PP */
180 if ((ctx
->raddr
& mmask
) != (pte1
& mmask
)) {
181 qemu_log("Bad RPN/WIMG/PP\n");
185 /* Compute access rights */
186 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
187 /* Keep the matching PTE informations */
190 ret
= check_prot(ctx
->prot
, rw
, type
);
193 LOG_MMU("PTE access granted !\n");
195 /* Access right violation */
196 LOG_MMU("PTE access rejected\n");
204 int pte_update_flags(mmu_ctx_t
*ctx
, target_ulong
*pte1p
,
209 /* Update page flags */
210 if (!(*pte1p
& 0x00000100)) {
211 /* Update accessed flag */
212 *pte1p
|= 0x00000100;
215 if (!(*pte1p
& 0x00000080)) {
216 if (rw
== 1 && ret
== 0) {
217 /* Update changed flag */
218 *pte1p
|= 0x00000080;
221 /* Force page fault for first write access */
222 ctx
->prot
&= ~PAGE_WRITE
;
229 /* Software driven TLB helpers */
230 static inline int ppc6xx_tlb_getnum(CPUPPCState
*env
, target_ulong eaddr
,
231 int way
, int is_code
)
235 /* Select TLB num in a way from address */
236 nr
= (eaddr
>> TARGET_PAGE_BITS
) & (env
->tlb_per_way
- 1);
238 nr
+= env
->tlb_per_way
* way
;
239 /* 6xx have separate TLBs for instructions and data */
240 if (is_code
&& env
->id_tlbs
== 1) {
247 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState
*env
)
252 /* LOG_SWTLB("Invalidate all TLBs\n"); */
253 /* Invalidate all defined software TLB */
255 if (env
->id_tlbs
== 1) {
258 for (nr
= 0; nr
< max
; nr
++) {
259 tlb
= &env
->tlb
.tlb6
[nr
];
260 pte_invalidate(&tlb
->pte0
);
265 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState
*env
,
267 int is_code
, int match_epn
)
269 #if !defined(FLUSH_ALL_TLBS)
273 /* Invalidate ITLB + DTLB, all ways */
274 for (way
= 0; way
< env
->nb_ways
; way
++) {
275 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
, is_code
);
276 tlb
= &env
->tlb
.tlb6
[nr
];
277 if (pte_is_valid(tlb
->pte0
) && (match_epn
== 0 || eaddr
== tlb
->EPN
)) {
278 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx
"\n", nr
,
280 pte_invalidate(&tlb
->pte0
);
281 tlb_flush_page(env
, tlb
->EPN
);
285 /* XXX: PowerPC specification say this is valid as well */
286 ppc6xx_tlb_invalidate_all(env
);
290 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState
*env
,
291 target_ulong eaddr
, int is_code
)
293 ppc6xx_tlb_invalidate_virt2(env
, eaddr
, is_code
, 0);
296 static void ppc6xx_tlb_store(CPUPPCState
*env
, target_ulong EPN
, int way
,
297 int is_code
, target_ulong pte0
, target_ulong pte1
)
302 nr
= ppc6xx_tlb_getnum(env
, EPN
, way
, is_code
);
303 tlb
= &env
->tlb
.tlb6
[nr
];
304 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
305 " PTE1 " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
, EPN
, pte0
, pte1
);
306 /* Invalidate any pending reference in QEMU for this virtual address */
307 ppc6xx_tlb_invalidate_virt2(env
, EPN
, is_code
, 1);
311 /* Store last way for LRU mechanism */
315 static inline int ppc6xx_tlb_check(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
316 target_ulong eaddr
, int rw
, int access_type
)
323 ret
= -1; /* No TLB found */
324 for (way
= 0; way
< env
->nb_ways
; way
++) {
325 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
,
326 access_type
== ACCESS_CODE
? 1 : 0);
327 tlb
= &env
->tlb
.tlb6
[nr
];
328 /* This test "emulates" the PTE index match for hardware TLBs */
329 if ((eaddr
& TARGET_PAGE_MASK
) != tlb
->EPN
) {
330 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx
" " TARGET_FMT_lx
331 "] <> " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
,
332 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
333 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
, eaddr
);
336 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx
" <> " TARGET_FMT_lx
" "
337 TARGET_FMT_lx
" %c %c\n", nr
, env
->nb_tlb
,
338 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
339 tlb
->EPN
, eaddr
, tlb
->pte1
,
340 rw
? 'S' : 'L', access_type
== ACCESS_CODE
? 'I' : 'D');
341 switch (ppc6xx_tlb_pte_check(ctx
, tlb
->pte0
, tlb
->pte1
, 0, rw
, access_type
)) {
343 /* TLB inconsistency */
346 /* Access violation */
356 /* XXX: we should go on looping to check all TLBs consistency
357 * but we can speed-up the whole thing as the
358 * result would be undefined if TLBs are not consistent.
367 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx
" prot=%01x ret=%d\n",
368 ctx
->raddr
& TARGET_PAGE_MASK
, ctx
->prot
, ret
);
369 /* Update page flags */
370 pte_update_flags(ctx
, &env
->tlb
.tlb6
[best
].pte1
, ret
, rw
);
376 /* Perform BAT hit & translation */
377 static inline void bat_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
378 int *validp
, int *protp
, target_ulong
*BATu
,
384 bl
= (*BATu
& 0x00001FFC) << 15;
387 if (((msr_pr
== 0) && (*BATu
& 0x00000002)) ||
388 ((msr_pr
!= 0) && (*BATu
& 0x00000001))) {
390 pp
= *BATl
& 0x00000003;
392 prot
= PAGE_READ
| PAGE_EXEC
;
403 static inline void bat_601_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
404 int *validp
, int *protp
,
405 target_ulong
*BATu
, target_ulong
*BATl
)
408 int key
, pp
, valid
, prot
;
410 bl
= (*BATl
& 0x0000003F) << 17;
411 LOG_BATS("b %02x ==> bl " TARGET_FMT_lx
" msk " TARGET_FMT_lx
"\n",
412 (uint8_t)(*BATl
& 0x0000003F), bl
, ~bl
);
414 valid
= (*BATl
>> 6) & 1;
416 pp
= *BATu
& 0x00000003;
418 key
= (*BATu
>> 3) & 1;
420 key
= (*BATu
>> 2) & 1;
422 prot
= pp_check(key
, pp
, 0);
429 int get_bat(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
430 target_ulong
virtual, int rw
, int type
)
432 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
433 target_ulong BEPIl
, BEPIu
, bl
;
437 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx
"\n", __func__
,
438 type
== ACCESS_CODE
? 'I' : 'D', virtual);
441 BATlt
= env
->IBAT
[1];
442 BATut
= env
->IBAT
[0];
445 BATlt
= env
->DBAT
[1];
446 BATut
= env
->DBAT
[0];
449 for (i
= 0; i
< env
->nb_BATs
; i
++) {
452 BEPIu
= *BATu
& 0xF0000000;
453 BEPIl
= *BATu
& 0x0FFE0000;
454 if (unlikely(env
->mmu_model
== POWERPC_MMU_601
)) {
455 bat_601_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
457 bat_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
459 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
460 " BATl " TARGET_FMT_lx
"\n", __func__
,
461 type
== ACCESS_CODE
? 'I' : 'D', i
, virtual, *BATu
, *BATl
);
462 if ((virtual & 0xF0000000) == BEPIu
&&
463 ((virtual & 0x0FFE0000) & ~bl
) == BEPIl
) {
466 /* Get physical address */
467 ctx
->raddr
= (*BATl
& 0xF0000000) |
468 ((virtual & 0x0FFE0000 & bl
) | (*BATl
& 0x0FFE0000)) |
469 (virtual & 0x0001F000);
470 /* Compute access rights */
472 ret
= check_prot(ctx
->prot
, rw
, type
);
474 LOG_BATS("BAT %d match: r " TARGET_FMT_plx
" prot=%c%c\n",
475 i
, ctx
->raddr
, ctx
->prot
& PAGE_READ
? 'R' : '-',
476 ctx
->prot
& PAGE_WRITE
? 'W' : '-');
483 #if defined(DEBUG_BATS)
484 if (qemu_log_enabled()) {
485 LOG_BATS("no BAT match for " TARGET_FMT_lx
":\n", virtual);
486 for (i
= 0; i
< 4; i
++) {
489 BEPIu
= *BATu
& 0xF0000000;
490 BEPIl
= *BATu
& 0x0FFE0000;
491 bl
= (*BATu
& 0x00001FFC) << 15;
492 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
493 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
494 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
495 __func__
, type
== ACCESS_CODE
? 'I' : 'D', i
, virtual,
496 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
505 hwaddr
get_pteg_offset(CPUPPCState
*env
, hwaddr hash
, int pte_size
)
507 return (hash
* pte_size
* 8) & env
->htab_mask
;
510 /* Perform segment based translation */
511 static inline int get_segment_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
512 target_ulong eaddr
, int rw
, int type
)
516 int ds
, pr
, target_page_bits
;
518 target_ulong sr
, pgidx
;
523 sr
= env
->sr
[eaddr
>> 28];
524 ctx
->key
= (((sr
& 0x20000000) && (pr
!= 0)) ||
525 ((sr
& 0x40000000) && (pr
== 0))) ? 1 : 0;
526 ds
= sr
& 0x80000000 ? 1 : 0;
527 ctx
->nx
= sr
& 0x10000000 ? 1 : 0;
528 vsid
= sr
& 0x00FFFFFF;
529 target_page_bits
= TARGET_PAGE_BITS
;
530 LOG_MMU("Check segment v=" TARGET_FMT_lx
" %d " TARGET_FMT_lx
" nip="
531 TARGET_FMT_lx
" lr=" TARGET_FMT_lx
532 " ir=%d dr=%d pr=%d %d t=%d\n",
533 eaddr
, (int)(eaddr
>> 28), sr
, env
->nip
, env
->lr
, (int)msr_ir
,
534 (int)msr_dr
, pr
!= 0 ? 1 : 0, rw
, type
);
535 pgidx
= (eaddr
& ~SEGMENT_MASK_256M
) >> target_page_bits
;
537 ctx
->ptem
= (vsid
<< 7) | (pgidx
>> 10);
539 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx
"\n",
540 ctx
->key
, ds
, ctx
->nx
, vsid
);
543 /* Check if instruction fetch is allowed, if needed */
544 if (type
!= ACCESS_CODE
|| ctx
->nx
== 0) {
545 /* Page address translation */
546 LOG_MMU("htab_base " TARGET_FMT_plx
" htab_mask " TARGET_FMT_plx
547 " hash " TARGET_FMT_plx
"\n",
548 env
->htab_base
, env
->htab_mask
, hash
);
550 ctx
->hash
[1] = ~hash
;
552 /* Initialize real address with an invalid value */
553 ctx
->raddr
= (hwaddr
)-1ULL;
554 /* Software TLB search */
555 ret
= ppc6xx_tlb_check(env
, ctx
, eaddr
, rw
, type
);
556 #if defined(DUMP_PAGE_TABLES)
557 if (qemu_log_enabled()) {
559 uint32_t a0
, a1
, a2
, a3
;
561 qemu_log("Page table: " TARGET_FMT_plx
" len " TARGET_FMT_plx
562 "\n", sdr
, mask
+ 0x80);
563 for (curaddr
= sdr
; curaddr
< (sdr
+ mask
+ 0x80);
565 a0
= ldl_phys(curaddr
);
566 a1
= ldl_phys(curaddr
+ 4);
567 a2
= ldl_phys(curaddr
+ 8);
568 a3
= ldl_phys(curaddr
+ 12);
569 if (a0
!= 0 || a1
!= 0 || a2
!= 0 || a3
!= 0) {
570 qemu_log(TARGET_FMT_plx
": %08x %08x %08x %08x\n",
571 curaddr
, a0
, a1
, a2
, a3
);
577 LOG_MMU("No access allowed\n");
583 LOG_MMU("direct store...\n");
584 /* Direct-store segment : absolutely *BUGGY* for now */
586 /* Direct-store implies a 32-bit MMU.
587 * Check the Segment Register's bus unit ID (BUID).
589 sr
= env
->sr
[eaddr
>> 28];
590 if ((sr
& 0x1FF00000) >> 20 == 0x07f) {
591 /* Memory-forced I/O controller interface access */
592 /* If T=1 and BUID=x'07F', the 601 performs a memory access
593 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
595 ctx
->raddr
= ((sr
& 0xF) << 28) | (eaddr
& 0x0FFFFFFF);
596 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
602 /* Integer load/store : only access allowed */
605 /* No code fetch is allowed in direct-store areas */
608 /* Floating point load/store */
611 /* lwarx, ldarx or srwcx. */
614 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
615 /* Should make the instruction do no-op.
616 * As it already do no-op, it's quite easy :-)
624 qemu_log("ERROR: instruction should not need "
625 "address translation\n");
628 if ((rw
== 1 || ctx
->key
!= 1) && (rw
== 0 || ctx
->key
!= 0)) {
639 /* Generic TLB check function for embedded PowerPC implementations */
640 static int ppcemb_tlb_check(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
642 target_ulong address
, uint32_t pid
, int ext
,
647 /* Check valid flag */
648 if (!(tlb
->prot
& PAGE_VALID
)) {
651 mask
= ~(tlb
->size
- 1);
652 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx
" PID %u <=> " TARGET_FMT_lx
653 " " TARGET_FMT_lx
" %u %x\n", __func__
, i
, address
, pid
, tlb
->EPN
,
654 mask
, (uint32_t)tlb
->PID
, tlb
->prot
);
656 if (tlb
->PID
!= 0 && tlb
->PID
!= pid
) {
659 /* Check effective address */
660 if ((address
& mask
) != tlb
->EPN
) {
663 *raddrp
= (tlb
->RPN
& mask
) | (address
& ~mask
);
665 /* Extend the physical address to 36 bits */
666 *raddrp
|= (uint64_t)(tlb
->RPN
& 0xF) << 32;
672 /* Generic TLB search function for PowerPC embedded implementations */
673 static int ppcemb_tlb_search(CPUPPCState
*env
, target_ulong address
,
680 /* Default return value is no match */
682 for (i
= 0; i
< env
->nb_tlb
; i
++) {
683 tlb
= &env
->tlb
.tlbe
[i
];
684 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
, pid
, 0, i
) == 0) {
693 /* Helpers specific to PowerPC 40x implementations */
694 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState
*env
)
699 for (i
= 0; i
< env
->nb_tlb
; i
++) {
700 tlb
= &env
->tlb
.tlbe
[i
];
701 tlb
->prot
&= ~PAGE_VALID
;
706 static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState
*env
,
707 target_ulong eaddr
, uint32_t pid
)
709 #if !defined(FLUSH_ALL_TLBS)
712 target_ulong page
, end
;
715 for (i
= 0; i
< env
->nb_tlb
; i
++) {
716 tlb
= &env
->tlb
.tlbe
[i
];
717 if (ppcemb_tlb_check(env
, tlb
, &raddr
, eaddr
, pid
, 0, i
) == 0) {
718 end
= tlb
->EPN
+ tlb
->size
;
719 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
720 tlb_flush_page(env
, page
);
722 tlb
->prot
&= ~PAGE_VALID
;
727 ppc4xx_tlb_invalidate_all(env
);
731 static int mmu40x_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
732 target_ulong address
, int rw
,
737 int i
, ret
, zsel
, zpr
, pr
;
740 raddr
= (hwaddr
)-1ULL;
742 for (i
= 0; i
< env
->nb_tlb
; i
++) {
743 tlb
= &env
->tlb
.tlbe
[i
];
744 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
745 env
->spr
[SPR_40x_PID
], 0, i
) < 0) {
748 zsel
= (tlb
->attr
>> 4) & 0xF;
749 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (30 - (2 * zsel
))) & 0x3;
750 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
751 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
752 /* Check execute enable bit */
760 /* All accesses granted */
761 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
766 /* Raise Zone protection fault. */
767 env
->spr
[SPR_40x_ESR
] = 1 << 22;
775 /* Check from TLB entry */
776 ctx
->prot
= tlb
->prot
;
777 ret
= check_prot(ctx
->prot
, rw
, access_type
);
779 env
->spr
[SPR_40x_ESR
] = 0;
785 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
786 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
791 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
792 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
797 void store_40x_sler(CPUPPCState
*env
, uint32_t val
)
799 /* XXX: TO BE FIXED */
800 if (val
!= 0x00000000) {
801 cpu_abort(env
, "Little-endian regions are not supported by now\n");
803 env
->spr
[SPR_405_SLER
] = val
;
806 static inline int mmubooke_check_tlb(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
807 hwaddr
*raddr
, int *prot
,
808 target_ulong address
, int rw
,
809 int access_type
, int i
)
813 if (ppcemb_tlb_check(env
, tlb
, raddr
, address
,
814 env
->spr
[SPR_BOOKE_PID
],
815 !env
->nb_pids
, i
) >= 0) {
819 if (env
->spr
[SPR_BOOKE_PID1
] &&
820 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
821 env
->spr
[SPR_BOOKE_PID1
], 0, i
) >= 0) {
825 if (env
->spr
[SPR_BOOKE_PID2
] &&
826 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
827 env
->spr
[SPR_BOOKE_PID2
], 0, i
) >= 0) {
831 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
837 prot2
= tlb
->prot
& 0xF;
839 prot2
= (tlb
->prot
>> 4) & 0xF;
842 /* Check the address space */
843 if (access_type
== ACCESS_CODE
) {
844 if (msr_ir
!= (tlb
->attr
& 1)) {
845 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
850 if (prot2
& PAGE_EXEC
) {
851 LOG_SWTLB("%s: good TLB!\n", __func__
);
855 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
858 if (msr_dr
!= (tlb
->attr
& 1)) {
859 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
864 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
865 LOG_SWTLB("%s: found TLB!\n", __func__
);
869 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
876 static int mmubooke_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
877 target_ulong address
, int rw
,
885 raddr
= (hwaddr
)-1ULL;
886 for (i
= 0; i
< env
->nb_tlb
; i
++) {
887 tlb
= &env
->tlb
.tlbe
[i
];
888 ret
= mmubooke_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
, rw
,
897 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
898 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
901 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
902 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
908 static void booke206_flush_tlb(CPUPPCState
*env
, int flags
,
909 const int check_iprot
)
913 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
915 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
916 if (flags
& (1 << i
)) {
917 tlb_size
= booke206_tlb_size(env
, i
);
918 for (j
= 0; j
< tlb_size
; j
++) {
919 if (!check_iprot
|| !(tlb
[j
].mas1
& MAS1_IPROT
)) {
920 tlb
[j
].mas1
&= ~MAS1_VALID
;
924 tlb
+= booke206_tlb_size(env
, i
);
930 static hwaddr
booke206_tlb_to_page_size(CPUPPCState
*env
,
935 tlbm_size
= (tlb
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
937 return 1024ULL << tlbm_size
;
940 /* TLB check function for MAS based SoftTLBs */
941 static int ppcmas_tlb_check(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
943 target_ulong address
, uint32_t pid
)
948 /* Check valid flag */
949 if (!(tlb
->mas1
& MAS1_VALID
)) {
953 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
954 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx
" PID=0x%x MAS1=0x%x MAS2=0x%"
955 PRIx64
" mask=0x" TARGET_FMT_lx
" MAS7_3=0x%" PRIx64
" MAS8=%x\n",
956 __func__
, address
, pid
, tlb
->mas1
, tlb
->mas2
, mask
, tlb
->mas7_3
,
960 tlb_pid
= (tlb
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
;
961 if (tlb_pid
!= 0 && tlb_pid
!= pid
) {
965 /* Check effective address */
966 if ((address
& mask
) != (tlb
->mas2
& MAS2_EPN_MASK
)) {
971 *raddrp
= (tlb
->mas7_3
& mask
) | (address
& ~mask
);
977 static int mmubooke206_check_tlb(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
978 hwaddr
*raddr
, int *prot
,
979 target_ulong address
, int rw
,
985 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
,
986 env
->spr
[SPR_BOOKE_PID
]) >= 0) {
990 if (env
->spr
[SPR_BOOKE_PID1
] &&
991 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
992 env
->spr
[SPR_BOOKE_PID1
]) >= 0) {
996 if (env
->spr
[SPR_BOOKE_PID2
] &&
997 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
998 env
->spr
[SPR_BOOKE_PID2
]) >= 0) {
1002 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
1008 if (tlb
->mas7_3
& MAS3_UR
) {
1011 if (tlb
->mas7_3
& MAS3_UW
) {
1012 prot2
|= PAGE_WRITE
;
1014 if (tlb
->mas7_3
& MAS3_UX
) {
1018 if (tlb
->mas7_3
& MAS3_SR
) {
1021 if (tlb
->mas7_3
& MAS3_SW
) {
1022 prot2
|= PAGE_WRITE
;
1024 if (tlb
->mas7_3
& MAS3_SX
) {
1029 /* Check the address space and permissions */
1030 if (access_type
== ACCESS_CODE
) {
1031 if (msr_ir
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1032 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1037 if (prot2
& PAGE_EXEC
) {
1038 LOG_SWTLB("%s: good TLB!\n", __func__
);
1042 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
1045 if (msr_dr
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1046 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1051 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
1052 LOG_SWTLB("%s: found TLB!\n", __func__
);
1056 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
1063 static int mmubooke206_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1064 target_ulong address
, int rw
,
1072 raddr
= (hwaddr
)-1ULL;
1074 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1075 int ways
= booke206_tlb_ways(env
, i
);
1077 for (j
= 0; j
< ways
; j
++) {
1078 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
1082 ret
= mmubooke206_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
,
1094 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
1095 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1098 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
1099 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
1105 static const char *book3e_tsize_to_str
[32] = {
1106 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1107 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1108 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1112 static void mmubooke_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1115 ppcemb_tlb_t
*entry
;
1118 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1119 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1123 cpu_fprintf(f
, "\nTLB:\n");
1124 cpu_fprintf(f
, "Effective Physical Size PID Prot "
1127 entry
= &env
->tlb
.tlbe
[0];
1128 for (i
= 0; i
< env
->nb_tlb
; i
++, entry
++) {
1131 uint64_t size
= (uint64_t)entry
->size
;
1134 /* Check valid flag */
1135 if (!(entry
->prot
& PAGE_VALID
)) {
1139 mask
= ~(entry
->size
- 1);
1140 ea
= entry
->EPN
& mask
;
1141 pa
= entry
->RPN
& mask
;
1142 /* Extend the physical address to 36 bits */
1143 pa
|= (hwaddr
)(entry
->RPN
& 0xF) << 32;
1146 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"M", size
/ 1024);
1148 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"k", size
);
1150 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %s %-5u %08x %08x\n",
1151 (uint64_t)ea
, (uint64_t)pa
, size_buf
, (uint32_t)entry
->PID
,
1152 entry
->prot
, entry
->attr
);
1157 static void mmubooke206_dump_one_tlb(FILE *f
, fprintf_function cpu_fprintf
,
1158 CPUPPCState
*env
, int tlbn
, int offset
,
1161 ppcmas_tlb_t
*entry
;
1164 cpu_fprintf(f
, "\nTLB%d:\n", tlbn
);
1165 cpu_fprintf(f
, "Effective Physical Size TID TS SRWX"
1166 " URWX WIMGE U0123\n");
1168 entry
= &env
->tlb
.tlbm
[offset
];
1169 for (i
= 0; i
< tlbsize
; i
++, entry
++) {
1170 hwaddr ea
, pa
, size
;
1173 if (!(entry
->mas1
& MAS1_VALID
)) {
1177 tsize
= (entry
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1178 size
= 1024ULL << tsize
;
1179 ea
= entry
->mas2
& ~(size
- 1);
1180 pa
= entry
->mas7_3
& ~(size
- 1);
1182 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %4s %-5u %1u S%c%c%c"
1183 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1184 (uint64_t)ea
, (uint64_t)pa
,
1185 book3e_tsize_to_str
[tsize
],
1186 (entry
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
,
1187 (entry
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
,
1188 entry
->mas7_3
& MAS3_SR
? 'R' : '-',
1189 entry
->mas7_3
& MAS3_SW
? 'W' : '-',
1190 entry
->mas7_3
& MAS3_SX
? 'X' : '-',
1191 entry
->mas7_3
& MAS3_UR
? 'R' : '-',
1192 entry
->mas7_3
& MAS3_UW
? 'W' : '-',
1193 entry
->mas7_3
& MAS3_UX
? 'X' : '-',
1194 entry
->mas2
& MAS2_W
? 'W' : '-',
1195 entry
->mas2
& MAS2_I
? 'I' : '-',
1196 entry
->mas2
& MAS2_M
? 'M' : '-',
1197 entry
->mas2
& MAS2_G
? 'G' : '-',
1198 entry
->mas2
& MAS2_E
? 'E' : '-',
1199 entry
->mas7_3
& MAS3_U0
? '0' : '-',
1200 entry
->mas7_3
& MAS3_U1
? '1' : '-',
1201 entry
->mas7_3
& MAS3_U2
? '2' : '-',
1202 entry
->mas7_3
& MAS3_U3
? '3' : '-');
1206 static void mmubooke206_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1212 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1213 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1217 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1218 int size
= booke206_tlb_size(env
, i
);
1224 mmubooke206_dump_one_tlb(f
, cpu_fprintf
, env
, i
, offset
, size
);
1229 void dump_mmu(FILE *f
, fprintf_function cpu_fprintf
, CPUPPCState
*env
)
1231 switch (env
->mmu_model
) {
1232 case POWERPC_MMU_BOOKE
:
1233 mmubooke_dump_mmu(f
, cpu_fprintf
, env
);
1235 case POWERPC_MMU_BOOKE206
:
1236 mmubooke206_dump_mmu(f
, cpu_fprintf
, env
);
1238 #if defined(TARGET_PPC64)
1239 case POWERPC_MMU_64B
:
1240 case POWERPC_MMU_2_06
:
1241 case POWERPC_MMU_2_06d
:
1242 dump_slb(f
, cpu_fprintf
, env
);
1246 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented\n", __func__
);
1250 static inline int check_physical(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1251 target_ulong eaddr
, int rw
)
1256 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1258 switch (env
->mmu_model
) {
1259 case POWERPC_MMU_SOFT_6xx
:
1260 case POWERPC_MMU_SOFT_74xx
:
1261 case POWERPC_MMU_SOFT_4xx
:
1262 case POWERPC_MMU_REAL
:
1263 case POWERPC_MMU_BOOKE
:
1264 ctx
->prot
|= PAGE_WRITE
;
1267 case POWERPC_MMU_SOFT_4xx_Z
:
1268 if (unlikely(msr_pe
!= 0)) {
1269 /* 403 family add some particular protections,
1270 * using PBL/PBU registers for accesses with no translation.
1273 /* Check PLB validity */
1274 (env
->pb
[0] < env
->pb
[1] &&
1275 /* and address in plb area */
1276 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1277 (env
->pb
[2] < env
->pb
[3] &&
1278 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1279 if (in_plb
^ msr_px
) {
1280 /* Access in protected area */
1282 /* Access is not allowed */
1286 /* Read-write access is allowed */
1287 ctx
->prot
|= PAGE_WRITE
;
1293 /* Caller's checks mean we should never get here for other models */
1301 static int get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1302 target_ulong eaddr
, int rw
, int access_type
)
1305 bool real_mode
= (access_type
== ACCESS_CODE
&& msr_ir
== 0)
1306 || (access_type
!= ACCESS_CODE
&& msr_dr
== 0);
1309 qemu_log("%s\n", __func__
);
1312 switch (env
->mmu_model
) {
1313 case POWERPC_MMU_32B
:
1314 case POWERPC_MMU_601
:
1315 ret
= ppc_hash32_get_physical_address(env
, ctx
, eaddr
, rw
, access_type
);
1318 case POWERPC_MMU_SOFT_6xx
:
1319 case POWERPC_MMU_SOFT_74xx
:
1321 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1323 /* Try to find a BAT */
1324 if (env
->nb_BATs
!= 0) {
1325 ret
= get_bat(env
, ctx
, eaddr
, rw
, access_type
);
1328 /* We didn't match any BAT entry or don't have BATs */
1329 ret
= get_segment_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1334 #if defined(TARGET_PPC64)
1335 case POWERPC_MMU_64B
:
1336 case POWERPC_MMU_2_06
:
1337 case POWERPC_MMU_2_06d
:
1338 ret
= ppc_hash64_get_physical_address(env
, ctx
, eaddr
, rw
, access_type
);
1342 case POWERPC_MMU_SOFT_4xx
:
1343 case POWERPC_MMU_SOFT_4xx_Z
:
1345 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1347 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1351 case POWERPC_MMU_BOOKE
:
1352 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1355 case POWERPC_MMU_BOOKE206
:
1356 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1359 case POWERPC_MMU_MPC8xx
:
1361 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1363 case POWERPC_MMU_REAL
:
1365 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1367 cpu_abort(env
, "PowerPC in real mode do not do any translation\n");
1371 cpu_abort(env
, "Unknown or invalid MMU model\n");
1375 qemu_log("%s address " TARGET_FMT_lx
" => %d " TARGET_FMT_plx
"\n",
1376 __func__
, eaddr
, ret
, ctx
->raddr
);
1382 hwaddr
cpu_get_phys_page_debug(CPUPPCState
*env
, target_ulong addr
)
1386 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0)) {
1390 return ctx
.raddr
& TARGET_PAGE_MASK
;
1393 static void booke206_update_mas_tlb_miss(CPUPPCState
*env
, target_ulong address
,
1396 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
1397 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
1398 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
1399 env
->spr
[SPR_BOOKE_MAS3
] = 0;
1400 env
->spr
[SPR_BOOKE_MAS6
] = 0;
1401 env
->spr
[SPR_BOOKE_MAS7
] = 0;
1404 if (((rw
== 2) && msr_ir
) || ((rw
!= 2) && msr_dr
)) {
1405 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
1406 env
->spr
[SPR_BOOKE_MAS6
] |= MAS6_SAS
;
1409 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_VALID
;
1410 env
->spr
[SPR_BOOKE_MAS2
] |= address
& MAS2_EPN_MASK
;
1412 switch (env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TIDSELD_PIDZ
) {
1413 case MAS4_TIDSELD_PID0
:
1414 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID
] << MAS1_TID_SHIFT
;
1416 case MAS4_TIDSELD_PID1
:
1417 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID1
] << MAS1_TID_SHIFT
;
1419 case MAS4_TIDSELD_PID2
:
1420 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID2
] << MAS1_TID_SHIFT
;
1424 env
->spr
[SPR_BOOKE_MAS6
] |= env
->spr
[SPR_BOOKE_PID
] << 16;
1426 /* next victim logic */
1427 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
1429 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
1430 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
1433 /* Perform address translation */
1434 int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
, int rw
,
1441 switch (env
->mmu_model
) {
1442 #if defined(TARGET_PPC64)
1443 case POWERPC_MMU_64B
:
1444 case POWERPC_MMU_2_06
:
1445 case POWERPC_MMU_2_06d
:
1446 return ppc_hash64_handle_mmu_fault(env
, address
, rw
, mmu_idx
);
1449 case POWERPC_MMU_32B
:
1450 case POWERPC_MMU_601
:
1451 return ppc_hash32_handle_mmu_fault(env
, address
, rw
, mmu_idx
);
1454 ; /* Otherwise fall through to the general code below */
1460 access_type
= ACCESS_CODE
;
1463 access_type
= env
->access_type
;
1465 ret
= get_physical_address(env
, &ctx
, address
, rw
, access_type
);
1467 tlb_set_page(env
, address
& TARGET_PAGE_MASK
,
1468 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1469 mmu_idx
, TARGET_PAGE_SIZE
);
1471 } else if (ret
< 0) {
1473 if (access_type
== ACCESS_CODE
) {
1476 /* No matches in page tables or TLB */
1477 switch (env
->mmu_model
) {
1478 case POWERPC_MMU_SOFT_6xx
:
1479 env
->exception_index
= POWERPC_EXCP_IFTLB
;
1480 env
->error_code
= 1 << 18;
1481 env
->spr
[SPR_IMISS
] = address
;
1482 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1484 case POWERPC_MMU_SOFT_74xx
:
1485 env
->exception_index
= POWERPC_EXCP_IFTLB
;
1487 case POWERPC_MMU_SOFT_4xx
:
1488 case POWERPC_MMU_SOFT_4xx_Z
:
1489 env
->exception_index
= POWERPC_EXCP_ITLB
;
1490 env
->error_code
= 0;
1491 env
->spr
[SPR_40x_DEAR
] = address
;
1492 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1494 case POWERPC_MMU_BOOKE206
:
1495 booke206_update_mas_tlb_miss(env
, address
, rw
);
1497 case POWERPC_MMU_BOOKE
:
1498 env
->exception_index
= POWERPC_EXCP_ITLB
;
1499 env
->error_code
= 0;
1500 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1502 case POWERPC_MMU_MPC8xx
:
1504 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1506 case POWERPC_MMU_REAL
:
1507 cpu_abort(env
, "PowerPC in real mode should never raise "
1508 "any MMU exceptions\n");
1511 cpu_abort(env
, "Unknown or invalid MMU model\n");
1516 /* Access rights violation */
1517 env
->exception_index
= POWERPC_EXCP_ISI
;
1518 env
->error_code
= 0x08000000;
1521 /* No execute protection violation */
1522 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1523 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1524 env
->spr
[SPR_BOOKE_ESR
] = 0x00000000;
1526 env
->exception_index
= POWERPC_EXCP_ISI
;
1527 env
->error_code
= 0x10000000;
1530 /* Direct store exception */
1531 /* No code fetch is allowed in direct-store areas */
1532 env
->exception_index
= POWERPC_EXCP_ISI
;
1533 env
->error_code
= 0x10000000;
1539 /* No matches in page tables or TLB */
1540 switch (env
->mmu_model
) {
1541 case POWERPC_MMU_SOFT_6xx
:
1543 env
->exception_index
= POWERPC_EXCP_DSTLB
;
1544 env
->error_code
= 1 << 16;
1546 env
->exception_index
= POWERPC_EXCP_DLTLB
;
1547 env
->error_code
= 0;
1549 env
->spr
[SPR_DMISS
] = address
;
1550 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1552 env
->error_code
|= ctx
.key
<< 19;
1553 env
->spr
[SPR_HASH1
] = env
->htab_base
+
1554 get_pteg_offset(env
, ctx
.hash
[0], HASH_PTE_SIZE_32
);
1555 env
->spr
[SPR_HASH2
] = env
->htab_base
+
1556 get_pteg_offset(env
, ctx
.hash
[1], HASH_PTE_SIZE_32
);
1558 case POWERPC_MMU_SOFT_74xx
:
1560 env
->exception_index
= POWERPC_EXCP_DSTLB
;
1562 env
->exception_index
= POWERPC_EXCP_DLTLB
;
1565 /* Implement LRU algorithm */
1566 env
->error_code
= ctx
.key
<< 19;
1567 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1568 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1569 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1571 case POWERPC_MMU_SOFT_4xx
:
1572 case POWERPC_MMU_SOFT_4xx_Z
:
1573 env
->exception_index
= POWERPC_EXCP_DTLB
;
1574 env
->error_code
= 0;
1575 env
->spr
[SPR_40x_DEAR
] = address
;
1577 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1579 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1582 case POWERPC_MMU_MPC8xx
:
1584 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1586 case POWERPC_MMU_BOOKE206
:
1587 booke206_update_mas_tlb_miss(env
, address
, rw
);
1589 case POWERPC_MMU_BOOKE
:
1590 env
->exception_index
= POWERPC_EXCP_DTLB
;
1591 env
->error_code
= 0;
1592 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1593 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1595 case POWERPC_MMU_REAL
:
1596 cpu_abort(env
, "PowerPC in real mode should never raise "
1597 "any MMU exceptions\n");
1600 cpu_abort(env
, "Unknown or invalid MMU model\n");
1605 /* Access rights violation */
1606 env
->exception_index
= POWERPC_EXCP_DSI
;
1607 env
->error_code
= 0;
1608 if (env
->mmu_model
== POWERPC_MMU_SOFT_4xx
1609 || env
->mmu_model
== POWERPC_MMU_SOFT_4xx_Z
) {
1610 env
->spr
[SPR_40x_DEAR
] = address
;
1612 env
->spr
[SPR_40x_ESR
] |= 0x00800000;
1614 } else if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1615 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1616 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1617 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1619 env
->spr
[SPR_DAR
] = address
;
1621 env
->spr
[SPR_DSISR
] = 0x0A000000;
1623 env
->spr
[SPR_DSISR
] = 0x08000000;
1628 /* Direct store exception */
1629 switch (access_type
) {
1631 /* Floating point load/store */
1632 env
->exception_index
= POWERPC_EXCP_ALIGN
;
1633 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1634 env
->spr
[SPR_DAR
] = address
;
1637 /* lwarx, ldarx or stwcx. */
1638 env
->exception_index
= POWERPC_EXCP_DSI
;
1639 env
->error_code
= 0;
1640 env
->spr
[SPR_DAR
] = address
;
1642 env
->spr
[SPR_DSISR
] = 0x06000000;
1644 env
->spr
[SPR_DSISR
] = 0x04000000;
1648 /* eciwx or ecowx */
1649 env
->exception_index
= POWERPC_EXCP_DSI
;
1650 env
->error_code
= 0;
1651 env
->spr
[SPR_DAR
] = address
;
1653 env
->spr
[SPR_DSISR
] = 0x06100000;
1655 env
->spr
[SPR_DSISR
] = 0x04100000;
1659 printf("DSI: invalid exception (%d)\n", ret
);
1660 env
->exception_index
= POWERPC_EXCP_PROGRAM
;
1662 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1663 env
->spr
[SPR_DAR
] = address
;
1670 printf("%s: set exception to %d %02x\n", __func__
,
1671 env
->exception
, env
->error_code
);
1679 /*****************************************************************************/
1680 /* BATs management */
1681 #if !defined(FLUSH_ALL_TLBS)
1682 static inline void do_invalidate_BAT(CPUPPCState
*env
, target_ulong BATu
,
1685 target_ulong base
, end
, page
;
1687 base
= BATu
& ~0x0001FFFF;
1688 end
= base
+ mask
+ 0x00020000;
1689 LOG_BATS("Flush BAT from " TARGET_FMT_lx
" to " TARGET_FMT_lx
" ("
1690 TARGET_FMT_lx
")\n", base
, end
, mask
);
1691 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
1692 tlb_flush_page(env
, page
);
1694 LOG_BATS("Flush done\n");
1698 static inline void dump_store_bat(CPUPPCState
*env
, char ID
, int ul
, int nr
,
1701 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx
" (" TARGET_FMT_lx
")\n", ID
,
1702 nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1705 void helper_store_ibatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1709 dump_store_bat(env
, 'I', 0, nr
, value
);
1710 if (env
->IBAT
[0][nr
] != value
) {
1711 mask
= (value
<< 15) & 0x0FFE0000UL
;
1712 #if !defined(FLUSH_ALL_TLBS)
1713 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1715 /* When storing valid upper BAT, mask BEPI and BRPN
1716 * and invalidate all TLBs covered by this BAT
1718 mask
= (value
<< 15) & 0x0FFE0000UL
;
1719 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1720 (value
& ~0x0001FFFFUL
& ~mask
);
1721 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1722 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1723 #if !defined(FLUSH_ALL_TLBS)
1724 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1731 void helper_store_ibatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1733 dump_store_bat(env
, 'I', 1, nr
, value
);
1734 env
->IBAT
[1][nr
] = value
;
1737 void helper_store_dbatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1741 dump_store_bat(env
, 'D', 0, nr
, value
);
1742 if (env
->DBAT
[0][nr
] != value
) {
1743 /* When storing valid upper BAT, mask BEPI and BRPN
1744 * and invalidate all TLBs covered by this BAT
1746 mask
= (value
<< 15) & 0x0FFE0000UL
;
1747 #if !defined(FLUSH_ALL_TLBS)
1748 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1750 mask
= (value
<< 15) & 0x0FFE0000UL
;
1751 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1752 (value
& ~0x0001FFFFUL
& ~mask
);
1753 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1754 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1755 #if !defined(FLUSH_ALL_TLBS)
1756 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1763 void helper_store_dbatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1765 dump_store_bat(env
, 'D', 1, nr
, value
);
1766 env
->DBAT
[1][nr
] = value
;
1769 void helper_store_601_batu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1772 #if defined(FLUSH_ALL_TLBS)
1776 dump_store_bat(env
, 'I', 0, nr
, value
);
1777 if (env
->IBAT
[0][nr
] != value
) {
1778 #if defined(FLUSH_ALL_TLBS)
1781 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1782 if (env
->IBAT
[1][nr
] & 0x40) {
1783 /* Invalidate BAT only if it is valid */
1784 #if !defined(FLUSH_ALL_TLBS)
1785 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1790 /* When storing valid upper BAT, mask BEPI and BRPN
1791 * and invalidate all TLBs covered by this BAT
1793 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1794 (value
& ~0x0001FFFFUL
& ~mask
);
1795 env
->DBAT
[0][nr
] = env
->IBAT
[0][nr
];
1796 if (env
->IBAT
[1][nr
] & 0x40) {
1797 #if !defined(FLUSH_ALL_TLBS)
1798 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1803 #if defined(FLUSH_ALL_TLBS)
1811 void helper_store_601_batl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1813 #if !defined(FLUSH_ALL_TLBS)
1819 dump_store_bat(env
, 'I', 1, nr
, value
);
1820 if (env
->IBAT
[1][nr
] != value
) {
1821 #if defined(FLUSH_ALL_TLBS)
1824 if (env
->IBAT
[1][nr
] & 0x40) {
1825 #if !defined(FLUSH_ALL_TLBS)
1826 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1827 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1833 #if !defined(FLUSH_ALL_TLBS)
1834 mask
= (value
<< 17) & 0x0FFE0000UL
;
1835 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1840 env
->IBAT
[1][nr
] = value
;
1841 env
->DBAT
[1][nr
] = value
;
1842 #if defined(FLUSH_ALL_TLBS)
1850 /*****************************************************************************/
1851 /* TLB management */
1852 void ppc_tlb_invalidate_all(CPUPPCState
*env
)
1854 switch (env
->mmu_model
) {
1855 case POWERPC_MMU_SOFT_6xx
:
1856 case POWERPC_MMU_SOFT_74xx
:
1857 ppc6xx_tlb_invalidate_all(env
);
1859 case POWERPC_MMU_SOFT_4xx
:
1860 case POWERPC_MMU_SOFT_4xx_Z
:
1861 ppc4xx_tlb_invalidate_all(env
);
1863 case POWERPC_MMU_REAL
:
1864 cpu_abort(env
, "No TLB for PowerPC 4xx in real mode\n");
1866 case POWERPC_MMU_MPC8xx
:
1868 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1870 case POWERPC_MMU_BOOKE
:
1873 case POWERPC_MMU_BOOKE206
:
1874 booke206_flush_tlb(env
, -1, 0);
1876 case POWERPC_MMU_32B
:
1877 case POWERPC_MMU_601
:
1878 #if defined(TARGET_PPC64)
1879 case POWERPC_MMU_64B
:
1880 case POWERPC_MMU_2_06
:
1881 case POWERPC_MMU_2_06d
:
1882 #endif /* defined(TARGET_PPC64) */
1887 cpu_abort(env
, "Unknown MMU model\n");
1892 void ppc_tlb_invalidate_one(CPUPPCState
*env
, target_ulong addr
)
1894 #if !defined(FLUSH_ALL_TLBS)
1895 addr
&= TARGET_PAGE_MASK
;
1896 switch (env
->mmu_model
) {
1897 case POWERPC_MMU_SOFT_6xx
:
1898 case POWERPC_MMU_SOFT_74xx
:
1899 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
1900 if (env
->id_tlbs
== 1) {
1901 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
1904 case POWERPC_MMU_SOFT_4xx
:
1905 case POWERPC_MMU_SOFT_4xx_Z
:
1906 ppc4xx_tlb_invalidate_virt(env
, addr
, env
->spr
[SPR_40x_PID
]);
1908 case POWERPC_MMU_REAL
:
1909 cpu_abort(env
, "No TLB for PowerPC 4xx in real mode\n");
1911 case POWERPC_MMU_MPC8xx
:
1913 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1915 case POWERPC_MMU_BOOKE
:
1917 cpu_abort(env
, "BookE MMU model is not implemented\n");
1919 case POWERPC_MMU_BOOKE206
:
1921 cpu_abort(env
, "BookE 2.06 MMU model is not implemented\n");
1923 case POWERPC_MMU_32B
:
1924 case POWERPC_MMU_601
:
1925 /* tlbie invalidate TLBs for all segments */
1926 addr
&= ~((target_ulong
)-1ULL << 28);
1927 /* XXX: this case should be optimized,
1928 * giving a mask to tlb_flush_page
1930 tlb_flush_page(env
, addr
| (0x0 << 28));
1931 tlb_flush_page(env
, addr
| (0x1 << 28));
1932 tlb_flush_page(env
, addr
| (0x2 << 28));
1933 tlb_flush_page(env
, addr
| (0x3 << 28));
1934 tlb_flush_page(env
, addr
| (0x4 << 28));
1935 tlb_flush_page(env
, addr
| (0x5 << 28));
1936 tlb_flush_page(env
, addr
| (0x6 << 28));
1937 tlb_flush_page(env
, addr
| (0x7 << 28));
1938 tlb_flush_page(env
, addr
| (0x8 << 28));
1939 tlb_flush_page(env
, addr
| (0x9 << 28));
1940 tlb_flush_page(env
, addr
| (0xA << 28));
1941 tlb_flush_page(env
, addr
| (0xB << 28));
1942 tlb_flush_page(env
, addr
| (0xC << 28));
1943 tlb_flush_page(env
, addr
| (0xD << 28));
1944 tlb_flush_page(env
, addr
| (0xE << 28));
1945 tlb_flush_page(env
, addr
| (0xF << 28));
1947 #if defined(TARGET_PPC64)
1948 case POWERPC_MMU_64B
:
1949 case POWERPC_MMU_2_06
:
1950 case POWERPC_MMU_2_06d
:
1951 /* tlbie invalidate TLBs for all segments */
1952 /* XXX: given the fact that there are too many segments to invalidate,
1953 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
1954 * we just invalidate all TLBs
1958 #endif /* defined(TARGET_PPC64) */
1961 cpu_abort(env
, "Unknown MMU model\n");
1965 ppc_tlb_invalidate_all(env
);
1969 /*****************************************************************************/
1970 /* Special registers manipulation */
1971 void ppc_store_sdr1(CPUPPCState
*env
, target_ulong value
)
1973 LOG_MMU("%s: " TARGET_FMT_lx
"\n", __func__
, value
);
1974 if (env
->spr
[SPR_SDR1
] != value
) {
1975 env
->spr
[SPR_SDR1
] = value
;
1976 #if defined(TARGET_PPC64)
1977 if (env
->mmu_model
& POWERPC_MMU_64
) {
1978 target_ulong htabsize
= value
& SDR_64_HTABSIZE
;
1980 if (htabsize
> 28) {
1981 fprintf(stderr
, "Invalid HTABSIZE 0x" TARGET_FMT_lx
1982 " stored in SDR1\n", htabsize
);
1985 env
->htab_mask
= (1ULL << (htabsize
+ 18)) - 1;
1986 env
->htab_base
= value
& SDR_64_HTABORG
;
1988 #endif /* defined(TARGET_PPC64) */
1990 /* FIXME: Should check for valid HTABMASK values */
1991 env
->htab_mask
= ((value
& SDR_32_HTABMASK
) << 16) | 0xFFFF;
1992 env
->htab_base
= value
& SDR_32_HTABORG
;
1998 /* Segment registers load and store */
1999 target_ulong
helper_load_sr(CPUPPCState
*env
, target_ulong sr_num
)
2001 #if defined(TARGET_PPC64)
2002 if (env
->mmu_model
& POWERPC_MMU_64
) {
2007 return env
->sr
[sr_num
];
2010 void helper_store_sr(CPUPPCState
*env
, target_ulong srnum
, target_ulong value
)
2012 LOG_MMU("%s: reg=%d " TARGET_FMT_lx
" " TARGET_FMT_lx
"\n", __func__
,
2013 (int)srnum
, value
, env
->sr
[srnum
]);
2014 #if defined(TARGET_PPC64)
2015 if (env
->mmu_model
& POWERPC_MMU_64
) {
2016 uint64_t rb
= 0, rs
= 0;
2019 rb
|= ((uint32_t)srnum
& 0xf) << 28;
2020 /* Set the valid bit */
2023 rb
|= (uint32_t)srnum
;
2026 rs
|= (value
& 0xfffffff) << 12;
2028 rs
|= ((value
>> 27) & 0xf) << 8;
2030 ppc_store_slb(env
, rb
, rs
);
2033 if (env
->sr
[srnum
] != value
) {
2034 env
->sr
[srnum
] = value
;
2035 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2036 flusing the whole TLB. */
2037 #if !defined(FLUSH_ALL_TLBS) && 0
2039 target_ulong page
, end
;
2040 /* Invalidate 256 MB of virtual memory */
2041 page
= (16 << 20) * srnum
;
2042 end
= page
+ (16 << 20);
2043 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
2044 tlb_flush_page(env
, page
);
2052 #endif /* !defined(CONFIG_USER_ONLY) */
2054 #if !defined(CONFIG_USER_ONLY)
2055 /* TLB management */
2056 void helper_tlbia(CPUPPCState
*env
)
2058 ppc_tlb_invalidate_all(env
);
2061 void helper_tlbie(CPUPPCState
*env
, target_ulong addr
)
2063 ppc_tlb_invalidate_one(env
, addr
);
2066 /* Software driven TLBs management */
2067 /* PowerPC 602/603 software TLB load instructions helpers */
2068 static void do_6xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2070 target_ulong RPN
, CMP
, EPN
;
2073 RPN
= env
->spr
[SPR_RPA
];
2075 CMP
= env
->spr
[SPR_ICMP
];
2076 EPN
= env
->spr
[SPR_IMISS
];
2078 CMP
= env
->spr
[SPR_DCMP
];
2079 EPN
= env
->spr
[SPR_DMISS
];
2081 way
= (env
->spr
[SPR_SRR1
] >> 17) & 1;
2082 (void)EPN
; /* avoid a compiler warning */
2083 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2084 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2086 /* Store this TLB */
2087 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2088 way
, is_code
, CMP
, RPN
);
2091 void helper_6xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2093 do_6xx_tlb(env
, EPN
, 0);
2096 void helper_6xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2098 do_6xx_tlb(env
, EPN
, 1);
2101 /* PowerPC 74xx software TLB load instructions helpers */
2102 static void do_74xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2104 target_ulong RPN
, CMP
, EPN
;
2107 RPN
= env
->spr
[SPR_PTELO
];
2108 CMP
= env
->spr
[SPR_PTEHI
];
2109 EPN
= env
->spr
[SPR_TLBMISS
] & ~0x3;
2110 way
= env
->spr
[SPR_TLBMISS
] & 0x3;
2111 (void)EPN
; /* avoid a compiler warning */
2112 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2113 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2115 /* Store this TLB */
2116 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2117 way
, is_code
, CMP
, RPN
);
2120 void helper_74xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2122 do_74xx_tlb(env
, EPN
, 0);
2125 void helper_74xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2127 do_74xx_tlb(env
, EPN
, 1);
2130 /*****************************************************************************/
2131 /* PowerPC 601 specific instructions (POWER bridge) */
2133 target_ulong
helper_rac(CPUPPCState
*env
, target_ulong addr
)
2137 target_ulong ret
= 0;
2139 /* We don't have to generate many instances of this instruction,
2140 * as rac is supervisor only.
2142 /* XXX: FIX THIS: Pretend we have no BAT */
2143 nb_BATs
= env
->nb_BATs
;
2145 if (get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) == 0) {
2148 env
->nb_BATs
= nb_BATs
;
2152 static inline target_ulong
booke_tlb_to_page_size(int size
)
2154 return 1024 << (2 * size
);
2157 static inline int booke_page_size_to_tlb(target_ulong page_size
)
2161 switch (page_size
) {
2195 #if defined(TARGET_PPC64)
2196 case 0x000100000000ULL
:
2199 case 0x000400000000ULL
:
2202 case 0x001000000000ULL
:
2205 case 0x004000000000ULL
:
2208 case 0x010000000000ULL
:
2220 /* Helpers for 4xx TLB management */
2221 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2223 #define PPC4XX_TLBHI_V 0x00000040
2224 #define PPC4XX_TLBHI_E 0x00000020
2225 #define PPC4XX_TLBHI_SIZE_MIN 0
2226 #define PPC4XX_TLBHI_SIZE_MAX 7
2227 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2228 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2229 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2231 #define PPC4XX_TLBLO_EX 0x00000200
2232 #define PPC4XX_TLBLO_WR 0x00000100
2233 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2234 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2236 target_ulong
helper_4xx_tlbre_hi(CPUPPCState
*env
, target_ulong entry
)
2242 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2243 tlb
= &env
->tlb
.tlbe
[entry
];
2245 if (tlb
->prot
& PAGE_VALID
) {
2246 ret
|= PPC4XX_TLBHI_V
;
2248 size
= booke_page_size_to_tlb(tlb
->size
);
2249 if (size
< PPC4XX_TLBHI_SIZE_MIN
|| size
> PPC4XX_TLBHI_SIZE_MAX
) {
2250 size
= PPC4XX_TLBHI_SIZE_DEFAULT
;
2252 ret
|= size
<< PPC4XX_TLBHI_SIZE_SHIFT
;
2253 env
->spr
[SPR_40x_PID
] = tlb
->PID
;
2257 target_ulong
helper_4xx_tlbre_lo(CPUPPCState
*env
, target_ulong entry
)
2262 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2263 tlb
= &env
->tlb
.tlbe
[entry
];
2265 if (tlb
->prot
& PAGE_EXEC
) {
2266 ret
|= PPC4XX_TLBLO_EX
;
2268 if (tlb
->prot
& PAGE_WRITE
) {
2269 ret
|= PPC4XX_TLBLO_WR
;
2274 void helper_4xx_tlbwe_hi(CPUPPCState
*env
, target_ulong entry
,
2278 target_ulong page
, end
;
2280 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2282 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2283 tlb
= &env
->tlb
.tlbe
[entry
];
2284 /* Invalidate previous TLB (if it's valid) */
2285 if (tlb
->prot
& PAGE_VALID
) {
2286 end
= tlb
->EPN
+ tlb
->size
;
2287 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx
" end "
2288 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2289 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2290 tlb_flush_page(env
, page
);
2293 tlb
->size
= booke_tlb_to_page_size((val
>> PPC4XX_TLBHI_SIZE_SHIFT
)
2294 & PPC4XX_TLBHI_SIZE_MASK
);
2295 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2296 * If this ever occurs, one should use the ppcemb target instead
2297 * of the ppc or ppc64 one
2299 if ((val
& PPC4XX_TLBHI_V
) && tlb
->size
< TARGET_PAGE_SIZE
) {
2300 cpu_abort(env
, "TLB size " TARGET_FMT_lu
" < %u "
2301 "are not supported (%d)\n",
2302 tlb
->size
, TARGET_PAGE_SIZE
, (int)((val
>> 7) & 0x7));
2304 tlb
->EPN
= val
& ~(tlb
->size
- 1);
2305 if (val
& PPC4XX_TLBHI_V
) {
2306 tlb
->prot
|= PAGE_VALID
;
2307 if (val
& PPC4XX_TLBHI_E
) {
2308 /* XXX: TO BE FIXED */
2310 "Little-endian TLB entries are not supported by now\n");
2313 tlb
->prot
&= ~PAGE_VALID
;
2315 tlb
->PID
= env
->spr
[SPR_40x_PID
]; /* PID */
2316 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2317 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2318 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2319 tlb
->prot
& PAGE_READ
? 'r' : '-',
2320 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2321 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2322 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2323 /* Invalidate new TLB (if valid) */
2324 if (tlb
->prot
& PAGE_VALID
) {
2325 end
= tlb
->EPN
+ tlb
->size
;
2326 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx
" end "
2327 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2328 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2329 tlb_flush_page(env
, page
);
2334 void helper_4xx_tlbwe_lo(CPUPPCState
*env
, target_ulong entry
,
2339 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2341 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2342 tlb
= &env
->tlb
.tlbe
[entry
];
2343 tlb
->attr
= val
& PPC4XX_TLBLO_ATTR_MASK
;
2344 tlb
->RPN
= val
& PPC4XX_TLBLO_RPN_MASK
;
2345 tlb
->prot
= PAGE_READ
;
2346 if (val
& PPC4XX_TLBLO_EX
) {
2347 tlb
->prot
|= PAGE_EXEC
;
2349 if (val
& PPC4XX_TLBLO_WR
) {
2350 tlb
->prot
|= PAGE_WRITE
;
2352 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2353 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2354 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2355 tlb
->prot
& PAGE_READ
? 'r' : '-',
2356 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2357 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2358 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2361 target_ulong
helper_4xx_tlbsx(CPUPPCState
*env
, target_ulong address
)
2363 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_40x_PID
]);
2366 /* PowerPC 440 TLB management */
2367 void helper_440_tlbwe(CPUPPCState
*env
, uint32_t word
, target_ulong entry
,
2371 target_ulong EPN
, RPN
, size
;
2374 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx
"\n",
2375 __func__
, word
, (int)entry
, value
);
2378 tlb
= &env
->tlb
.tlbe
[entry
];
2381 /* Just here to please gcc */
2383 EPN
= value
& 0xFFFFFC00;
2384 if ((tlb
->prot
& PAGE_VALID
) && EPN
!= tlb
->EPN
) {
2388 size
= booke_tlb_to_page_size((value
>> 4) & 0xF);
2389 if ((tlb
->prot
& PAGE_VALID
) && tlb
->size
< size
) {
2394 tlb
->attr
|= (value
>> 8) & 1;
2395 if (value
& 0x200) {
2396 tlb
->prot
|= PAGE_VALID
;
2398 if (tlb
->prot
& PAGE_VALID
) {
2399 tlb
->prot
&= ~PAGE_VALID
;
2403 tlb
->PID
= env
->spr
[SPR_440_MMUCR
] & 0x000000FF;
2404 if (do_flush_tlbs
) {
2409 RPN
= value
& 0xFFFFFC0F;
2410 if ((tlb
->prot
& PAGE_VALID
) && tlb
->RPN
!= RPN
) {
2416 tlb
->attr
= (tlb
->attr
& 0x1) | (value
& 0x0000FF00);
2417 tlb
->prot
= tlb
->prot
& PAGE_VALID
;
2419 tlb
->prot
|= PAGE_READ
<< 4;
2422 tlb
->prot
|= PAGE_WRITE
<< 4;
2425 tlb
->prot
|= PAGE_EXEC
<< 4;
2428 tlb
->prot
|= PAGE_READ
;
2431 tlb
->prot
|= PAGE_WRITE
;
2434 tlb
->prot
|= PAGE_EXEC
;
2440 target_ulong
helper_440_tlbre(CPUPPCState
*env
, uint32_t word
,
2448 tlb
= &env
->tlb
.tlbe
[entry
];
2451 /* Just here to please gcc */
2454 size
= booke_page_size_to_tlb(tlb
->size
);
2455 if (size
< 0 || size
> 0xF) {
2459 if (tlb
->attr
& 0x1) {
2462 if (tlb
->prot
& PAGE_VALID
) {
2465 env
->spr
[SPR_440_MMUCR
] &= ~0x000000FF;
2466 env
->spr
[SPR_440_MMUCR
] |= tlb
->PID
;
2472 ret
= tlb
->attr
& ~0x1;
2473 if (tlb
->prot
& (PAGE_READ
<< 4)) {
2476 if (tlb
->prot
& (PAGE_WRITE
<< 4)) {
2479 if (tlb
->prot
& (PAGE_EXEC
<< 4)) {
2482 if (tlb
->prot
& PAGE_READ
) {
2485 if (tlb
->prot
& PAGE_WRITE
) {
2488 if (tlb
->prot
& PAGE_EXEC
) {
2496 target_ulong
helper_440_tlbsx(CPUPPCState
*env
, target_ulong address
)
2498 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_440_MMUCR
] & 0xFF);
2501 /* PowerPC BookE 2.06 TLB management */
2503 static ppcmas_tlb_t
*booke206_cur_tlb(CPUPPCState
*env
)
2505 uint32_t tlbncfg
= 0;
2506 int esel
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ESEL_MASK
) >> MAS0_ESEL_SHIFT
;
2507 int ea
= (env
->spr
[SPR_BOOKE_MAS2
] & MAS2_EPN_MASK
);
2510 tlb
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2511 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlb
];
2513 if ((tlbncfg
& TLBnCFG_HES
) && (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_HES
)) {
2514 cpu_abort(env
, "we don't support HES yet\n");
2517 return booke206_get_tlbm(env
, tlb
, ea
, esel
);
2520 void helper_booke_setpid(CPUPPCState
*env
, uint32_t pidn
, target_ulong pid
)
2522 env
->spr
[pidn
] = pid
;
2523 /* changing PIDs mean we're in a different address space now */
2527 void helper_booke206_tlbwe(CPUPPCState
*env
)
2529 uint32_t tlbncfg
, tlbn
;
2531 uint32_t size_tlb
, size_ps
;
2535 switch (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_WQ_MASK
) {
2536 case MAS0_WQ_ALWAYS
:
2537 /* good to go, write that entry */
2540 /* XXX check if reserved */
2545 case MAS0_WQ_CLR_RSRV
:
2546 /* XXX clear entry */
2549 /* no idea what to do */
2553 if (((env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ATSEL
) == MAS0_ATSEL_LRAT
) &&
2555 /* XXX we don't support direct LRAT setting yet */
2556 fprintf(stderr
, "cpu: don't support LRAT setting yet\n");
2560 tlbn
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2561 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlbn
];
2563 tlb
= booke206_cur_tlb(env
);
2566 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2567 POWERPC_EXCP_INVAL
|
2568 POWERPC_EXCP_INVAL_INVAL
);
2571 /* check that we support the targeted size */
2572 size_tlb
= (env
->spr
[SPR_BOOKE_MAS1
] & MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
2573 size_ps
= booke206_tlbnps(env
, tlbn
);
2574 if ((env
->spr
[SPR_BOOKE_MAS1
] & MAS1_VALID
) && (tlbncfg
& TLBnCFG_AVAIL
) &&
2575 !(size_ps
& (1 << size_tlb
))) {
2576 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2577 POWERPC_EXCP_INVAL
|
2578 POWERPC_EXCP_INVAL_INVAL
);
2582 cpu_abort(env
, "missing HV implementation\n");
2584 tlb
->mas7_3
= ((uint64_t)env
->spr
[SPR_BOOKE_MAS7
] << 32) |
2585 env
->spr
[SPR_BOOKE_MAS3
];
2586 tlb
->mas1
= env
->spr
[SPR_BOOKE_MAS1
];
2589 if (!(tlbncfg
& TLBnCFG_AVAIL
)) {
2590 /* force !AVAIL TLB entries to correct page size */
2591 tlb
->mas1
&= ~MAS1_TSIZE_MASK
;
2592 /* XXX can be configured in MMUCSR0 */
2593 tlb
->mas1
|= (tlbncfg
& TLBnCFG_MINSIZE
) >> 12;
2596 /* Make a mask from TLB size to discard invalid bits in EPN field */
2597 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2598 /* Add a mask for page attributes */
2599 mask
|= MAS2_ACM
| MAS2_VLE
| MAS2_W
| MAS2_I
| MAS2_M
| MAS2_G
| MAS2_E
;
2602 /* Executing a tlbwe instruction in 32-bit mode will set
2603 * bits 0:31 of the TLB EPN field to zero.
2608 tlb
->mas2
= env
->spr
[SPR_BOOKE_MAS2
] & mask
;
2610 if (!(tlbncfg
& TLBnCFG_IPROT
)) {
2611 /* no IPROT supported by TLB */
2612 tlb
->mas1
&= ~MAS1_IPROT
;
2615 if (booke206_tlb_to_page_size(env
, tlb
) == TARGET_PAGE_SIZE
) {
2616 tlb_flush_page(env
, tlb
->mas2
& MAS2_EPN_MASK
);
2622 static inline void booke206_tlb_to_mas(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2624 int tlbn
= booke206_tlbm_to_tlbn(env
, tlb
);
2625 int way
= booke206_tlbm_to_way(env
, tlb
);
2627 env
->spr
[SPR_BOOKE_MAS0
] = tlbn
<< MAS0_TLBSEL_SHIFT
;
2628 env
->spr
[SPR_BOOKE_MAS0
] |= way
<< MAS0_ESEL_SHIFT
;
2629 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2631 env
->spr
[SPR_BOOKE_MAS1
] = tlb
->mas1
;
2632 env
->spr
[SPR_BOOKE_MAS2
] = tlb
->mas2
;
2633 env
->spr
[SPR_BOOKE_MAS3
] = tlb
->mas7_3
;
2634 env
->spr
[SPR_BOOKE_MAS7
] = tlb
->mas7_3
>> 32;
2637 void helper_booke206_tlbre(CPUPPCState
*env
)
2639 ppcmas_tlb_t
*tlb
= NULL
;
2641 tlb
= booke206_cur_tlb(env
);
2643 env
->spr
[SPR_BOOKE_MAS1
] = 0;
2645 booke206_tlb_to_mas(env
, tlb
);
2649 void helper_booke206_tlbsx(CPUPPCState
*env
, target_ulong address
)
2651 ppcmas_tlb_t
*tlb
= NULL
;
2656 spid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID_MASK
) >> MAS6_SPID_SHIFT
;
2657 sas
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
;
2659 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2660 int ways
= booke206_tlb_ways(env
, i
);
2662 for (j
= 0; j
< ways
; j
++) {
2663 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2669 if (ppcmas_tlb_check(env
, tlb
, &raddr
, address
, spid
)) {
2673 if (sas
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
2677 booke206_tlb_to_mas(env
, tlb
);
2682 /* no entry found, fill with defaults */
2683 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
2684 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
2685 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
2686 env
->spr
[SPR_BOOKE_MAS3
] = 0;
2687 env
->spr
[SPR_BOOKE_MAS7
] = 0;
2689 if (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
) {
2690 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
2693 env
->spr
[SPR_BOOKE_MAS1
] |= (env
->spr
[SPR_BOOKE_MAS6
] >> 16)
2696 /* next victim logic */
2697 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
2699 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
2700 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2703 static inline void booke206_invalidate_ea_tlb(CPUPPCState
*env
, int tlbn
,
2707 int ways
= booke206_tlb_ways(env
, tlbn
);
2710 for (i
= 0; i
< ways
; i
++) {
2711 ppcmas_tlb_t
*tlb
= booke206_get_tlbm(env
, tlbn
, ea
, i
);
2715 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2716 if (((tlb
->mas2
& MAS2_EPN_MASK
) == (ea
& mask
)) &&
2717 !(tlb
->mas1
& MAS1_IPROT
)) {
2718 tlb
->mas1
&= ~MAS1_VALID
;
2723 void helper_booke206_tlbivax(CPUPPCState
*env
, target_ulong address
)
2725 if (address
& 0x4) {
2726 /* flush all entries */
2727 if (address
& 0x8) {
2728 /* flush all of TLB1 */
2729 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB1
, 1);
2731 /* flush all of TLB0 */
2732 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB0
, 0);
2737 if (address
& 0x8) {
2738 /* flush TLB1 entries */
2739 booke206_invalidate_ea_tlb(env
, 1, address
);
2742 /* flush TLB0 entries */
2743 booke206_invalidate_ea_tlb(env
, 0, address
);
2744 tlb_flush_page(env
, address
& MAS2_EPN_MASK
);
2748 void helper_booke206_tlbilx0(CPUPPCState
*env
, target_ulong address
)
2750 /* XXX missing LPID handling */
2751 booke206_flush_tlb(env
, -1, 1);
2754 void helper_booke206_tlbilx1(CPUPPCState
*env
, target_ulong address
)
2757 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2758 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
2761 /* XXX missing LPID handling */
2762 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2763 tlb_size
= booke206_tlb_size(env
, i
);
2764 for (j
= 0; j
< tlb_size
; j
++) {
2765 if (!(tlb
[j
].mas1
& MAS1_IPROT
) &&
2766 ((tlb
[j
].mas1
& MAS1_TID_MASK
) == tid
)) {
2767 tlb
[j
].mas1
&= ~MAS1_VALID
;
2770 tlb
+= booke206_tlb_size(env
, i
);
2775 void helper_booke206_tlbilx3(CPUPPCState
*env
, target_ulong address
)
2779 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2780 int pid
= tid
>> MAS6_SPID_SHIFT
;
2781 int sgs
= env
->spr
[SPR_BOOKE_MAS5
] & MAS5_SGS
;
2782 int ind
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SIND
) ? MAS1_IND
: 0;
2783 /* XXX check for unsupported isize and raise an invalid opcode then */
2784 int size
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_ISIZE_MASK
;
2785 /* XXX implement MAV2 handling */
2788 /* XXX missing LPID handling */
2789 /* flush by pid and ea */
2790 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2791 int ways
= booke206_tlb_ways(env
, i
);
2793 for (j
= 0; j
< ways
; j
++) {
2794 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2798 if ((ppcmas_tlb_check(env
, tlb
, NULL
, address
, pid
) != 0) ||
2799 (tlb
->mas1
& MAS1_IPROT
) ||
2800 ((tlb
->mas1
& MAS1_IND
) != ind
) ||
2801 ((tlb
->mas8
& MAS8_TGS
) != sgs
)) {
2804 if (mav2
&& ((tlb
->mas1
& MAS1_TSIZE_MASK
) != size
)) {
2805 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2808 /* XXX e500mc doesn't match SAS, but other cores might */
2809 tlb
->mas1
&= ~MAS1_VALID
;
2815 void helper_booke206_tlbflush(CPUPPCState
*env
, uint32_t type
)
2820 flags
|= BOOKE206_FLUSH_TLB1
;
2824 flags
|= BOOKE206_FLUSH_TLB0
;
2827 booke206_flush_tlb(env
, flags
, 1);