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
;
81 /* Context used internally during MMU translations */
82 typedef struct mmu_ctx_t mmu_ctx_t
;
84 hwaddr raddr
; /* Real address */
85 hwaddr eaddr
; /* Effective address */
86 int prot
; /* Protection bits */
87 hwaddr hash
[2]; /* Pagetable hash values */
88 target_ulong ptem
; /* Virtual segment ID | API */
89 int key
; /* Access key */
90 int nx
; /* Non-execute area */
93 /* Common routines used by software and hardware TLBs emulation */
94 static inline int pte_is_valid(target_ulong pte0
)
96 return pte0
& 0x80000000 ? 1 : 0;
99 static inline void pte_invalidate(target_ulong
*pte0
)
101 *pte0
&= ~0x80000000;
104 #define PTE_PTEM_MASK 0x7FFFFFBF
105 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
107 static int pp_check(int key
, int pp
, int nx
)
111 /* Compute access rights */
118 access
|= PAGE_WRITE
;
134 access
= PAGE_READ
| PAGE_WRITE
;
145 static int check_prot(int prot
, int rw
, int access_type
)
149 if (access_type
== ACCESS_CODE
) {
150 if (prot
& PAGE_EXEC
) {
156 if (prot
& PAGE_WRITE
) {
162 if (prot
& PAGE_READ
) {
172 static inline int ppc6xx_tlb_pte_check(mmu_ctx_t
*ctx
, target_ulong pte0
,
173 target_ulong pte1
, int h
, int rw
, int type
)
175 target_ulong ptem
, mmask
;
176 int access
, ret
, pteh
, ptev
, pp
;
179 /* Check validity and table match */
180 ptev
= pte_is_valid(pte0
);
181 pteh
= (pte0
>> 6) & 1;
182 if (ptev
&& h
== pteh
) {
183 /* Check vsid & api */
184 ptem
= pte0
& PTE_PTEM_MASK
;
185 mmask
= PTE_CHECK_MASK
;
186 pp
= pte1
& 0x00000003;
187 if (ptem
== ctx
->ptem
) {
188 if (ctx
->raddr
!= (hwaddr
)-1ULL) {
189 /* all matches should have equal RPN, WIMG & PP */
190 if ((ctx
->raddr
& mmask
) != (pte1
& mmask
)) {
191 qemu_log("Bad RPN/WIMG/PP\n");
195 /* Compute access rights */
196 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
197 /* Keep the matching PTE informations */
200 ret
= check_prot(ctx
->prot
, rw
, type
);
203 LOG_MMU("PTE access granted !\n");
205 /* Access right violation */
206 LOG_MMU("PTE access rejected\n");
214 static int pte_update_flags(mmu_ctx_t
*ctx
, target_ulong
*pte1p
,
219 /* Update page flags */
220 if (!(*pte1p
& 0x00000100)) {
221 /* Update accessed flag */
222 *pte1p
|= 0x00000100;
225 if (!(*pte1p
& 0x00000080)) {
226 if (rw
== 1 && ret
== 0) {
227 /* Update changed flag */
228 *pte1p
|= 0x00000080;
231 /* Force page fault for first write access */
232 ctx
->prot
&= ~PAGE_WRITE
;
239 /* Software driven TLB helpers */
240 static inline int ppc6xx_tlb_getnum(CPUPPCState
*env
, target_ulong eaddr
,
241 int way
, int is_code
)
245 /* Select TLB num in a way from address */
246 nr
= (eaddr
>> TARGET_PAGE_BITS
) & (env
->tlb_per_way
- 1);
248 nr
+= env
->tlb_per_way
* way
;
249 /* 6xx have separate TLBs for instructions and data */
250 if (is_code
&& env
->id_tlbs
== 1) {
257 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState
*env
)
262 /* LOG_SWTLB("Invalidate all TLBs\n"); */
263 /* Invalidate all defined software TLB */
265 if (env
->id_tlbs
== 1) {
268 for (nr
= 0; nr
< max
; nr
++) {
269 tlb
= &env
->tlb
.tlb6
[nr
];
270 pte_invalidate(&tlb
->pte0
);
275 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState
*env
,
277 int is_code
, int match_epn
)
279 #if !defined(FLUSH_ALL_TLBS)
283 /* Invalidate ITLB + DTLB, all ways */
284 for (way
= 0; way
< env
->nb_ways
; way
++) {
285 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
, is_code
);
286 tlb
= &env
->tlb
.tlb6
[nr
];
287 if (pte_is_valid(tlb
->pte0
) && (match_epn
== 0 || eaddr
== tlb
->EPN
)) {
288 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx
"\n", nr
,
290 pte_invalidate(&tlb
->pte0
);
291 tlb_flush_page(env
, tlb
->EPN
);
295 /* XXX: PowerPC specification say this is valid as well */
296 ppc6xx_tlb_invalidate_all(env
);
300 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState
*env
,
301 target_ulong eaddr
, int is_code
)
303 ppc6xx_tlb_invalidate_virt2(env
, eaddr
, is_code
, 0);
306 static void ppc6xx_tlb_store(CPUPPCState
*env
, target_ulong EPN
, int way
,
307 int is_code
, target_ulong pte0
, target_ulong pte1
)
312 nr
= ppc6xx_tlb_getnum(env
, EPN
, way
, is_code
);
313 tlb
= &env
->tlb
.tlb6
[nr
];
314 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
315 " PTE1 " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
, EPN
, pte0
, pte1
);
316 /* Invalidate any pending reference in QEMU for this virtual address */
317 ppc6xx_tlb_invalidate_virt2(env
, EPN
, is_code
, 1);
321 /* Store last way for LRU mechanism */
325 static inline int ppc6xx_tlb_check(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
326 target_ulong eaddr
, int rw
, int access_type
)
333 ret
= -1; /* No TLB found */
334 for (way
= 0; way
< env
->nb_ways
; way
++) {
335 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
,
336 access_type
== ACCESS_CODE
? 1 : 0);
337 tlb
= &env
->tlb
.tlb6
[nr
];
338 /* This test "emulates" the PTE index match for hardware TLBs */
339 if ((eaddr
& TARGET_PAGE_MASK
) != tlb
->EPN
) {
340 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx
" " TARGET_FMT_lx
341 "] <> " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
,
342 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
343 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
, eaddr
);
346 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx
" <> " TARGET_FMT_lx
" "
347 TARGET_FMT_lx
" %c %c\n", nr
, env
->nb_tlb
,
348 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
349 tlb
->EPN
, eaddr
, tlb
->pte1
,
350 rw
? 'S' : 'L', access_type
== ACCESS_CODE
? 'I' : 'D');
351 switch (ppc6xx_tlb_pte_check(ctx
, tlb
->pte0
, tlb
->pte1
, 0, rw
, access_type
)) {
353 /* TLB inconsistency */
356 /* Access violation */
366 /* XXX: we should go on looping to check all TLBs consistency
367 * but we can speed-up the whole thing as the
368 * result would be undefined if TLBs are not consistent.
377 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx
" prot=%01x ret=%d\n",
378 ctx
->raddr
& TARGET_PAGE_MASK
, ctx
->prot
, ret
);
379 /* Update page flags */
380 pte_update_flags(ctx
, &env
->tlb
.tlb6
[best
].pte1
, ret
, rw
);
386 /* Perform BAT hit & translation */
387 static inline void bat_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
388 int *validp
, int *protp
, target_ulong
*BATu
,
394 bl
= (*BATu
& 0x00001FFC) << 15;
397 if (((msr_pr
== 0) && (*BATu
& 0x00000002)) ||
398 ((msr_pr
!= 0) && (*BATu
& 0x00000001))) {
400 pp
= *BATl
& 0x00000003;
402 prot
= PAGE_READ
| PAGE_EXEC
;
413 static int get_bat_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
414 target_ulong
virtual, int rw
, int type
)
416 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
417 target_ulong BEPIl
, BEPIu
, bl
;
421 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx
"\n", __func__
,
422 type
== ACCESS_CODE
? 'I' : 'D', virtual);
425 BATlt
= env
->IBAT
[1];
426 BATut
= env
->IBAT
[0];
429 BATlt
= env
->DBAT
[1];
430 BATut
= env
->DBAT
[0];
433 for (i
= 0; i
< env
->nb_BATs
; i
++) {
436 BEPIu
= *BATu
& 0xF0000000;
437 BEPIl
= *BATu
& 0x0FFE0000;
438 bat_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
439 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
440 " BATl " TARGET_FMT_lx
"\n", __func__
,
441 type
== ACCESS_CODE
? 'I' : 'D', i
, virtual, *BATu
, *BATl
);
442 if ((virtual & 0xF0000000) == BEPIu
&&
443 ((virtual & 0x0FFE0000) & ~bl
) == BEPIl
) {
446 /* Get physical address */
447 ctx
->raddr
= (*BATl
& 0xF0000000) |
448 ((virtual & 0x0FFE0000 & bl
) | (*BATl
& 0x0FFE0000)) |
449 (virtual & 0x0001F000);
450 /* Compute access rights */
452 ret
= check_prot(ctx
->prot
, rw
, type
);
454 LOG_BATS("BAT %d match: r " TARGET_FMT_plx
" prot=%c%c\n",
455 i
, ctx
->raddr
, ctx
->prot
& PAGE_READ
? 'R' : '-',
456 ctx
->prot
& PAGE_WRITE
? 'W' : '-');
463 #if defined(DEBUG_BATS)
464 if (qemu_log_enabled()) {
465 LOG_BATS("no BAT match for " TARGET_FMT_lx
":\n", virtual);
466 for (i
= 0; i
< 4; i
++) {
469 BEPIu
= *BATu
& 0xF0000000;
470 BEPIl
= *BATu
& 0x0FFE0000;
471 bl
= (*BATu
& 0x00001FFC) << 15;
472 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
473 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
474 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
475 __func__
, type
== ACCESS_CODE
? 'I' : 'D', i
, virtual,
476 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
485 /* Perform segment based translation */
486 static inline int get_segment_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
487 target_ulong eaddr
, int rw
, int type
)
491 int ds
, pr
, target_page_bits
;
493 target_ulong sr
, pgidx
;
498 sr
= env
->sr
[eaddr
>> 28];
499 ctx
->key
= (((sr
& 0x20000000) && (pr
!= 0)) ||
500 ((sr
& 0x40000000) && (pr
== 0))) ? 1 : 0;
501 ds
= sr
& 0x80000000 ? 1 : 0;
502 ctx
->nx
= sr
& 0x10000000 ? 1 : 0;
503 vsid
= sr
& 0x00FFFFFF;
504 target_page_bits
= TARGET_PAGE_BITS
;
505 LOG_MMU("Check segment v=" TARGET_FMT_lx
" %d " TARGET_FMT_lx
" nip="
506 TARGET_FMT_lx
" lr=" TARGET_FMT_lx
507 " ir=%d dr=%d pr=%d %d t=%d\n",
508 eaddr
, (int)(eaddr
>> 28), sr
, env
->nip
, env
->lr
, (int)msr_ir
,
509 (int)msr_dr
, pr
!= 0 ? 1 : 0, rw
, type
);
510 pgidx
= (eaddr
& ~SEGMENT_MASK_256M
) >> target_page_bits
;
512 ctx
->ptem
= (vsid
<< 7) | (pgidx
>> 10);
514 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx
"\n",
515 ctx
->key
, ds
, ctx
->nx
, vsid
);
518 /* Check if instruction fetch is allowed, if needed */
519 if (type
!= ACCESS_CODE
|| ctx
->nx
== 0) {
520 /* Page address translation */
521 LOG_MMU("htab_base " TARGET_FMT_plx
" htab_mask " TARGET_FMT_plx
522 " hash " TARGET_FMT_plx
"\n",
523 env
->htab_base
, env
->htab_mask
, hash
);
525 ctx
->hash
[1] = ~hash
;
527 /* Initialize real address with an invalid value */
528 ctx
->raddr
= (hwaddr
)-1ULL;
529 /* Software TLB search */
530 ret
= ppc6xx_tlb_check(env
, ctx
, eaddr
, rw
, type
);
531 #if defined(DUMP_PAGE_TABLES)
532 if (qemu_log_enabled()) {
534 uint32_t a0
, a1
, a2
, a3
;
536 qemu_log("Page table: " TARGET_FMT_plx
" len " TARGET_FMT_plx
537 "\n", sdr
, mask
+ 0x80);
538 for (curaddr
= sdr
; curaddr
< (sdr
+ mask
+ 0x80);
540 a0
= ldl_phys(curaddr
);
541 a1
= ldl_phys(curaddr
+ 4);
542 a2
= ldl_phys(curaddr
+ 8);
543 a3
= ldl_phys(curaddr
+ 12);
544 if (a0
!= 0 || a1
!= 0 || a2
!= 0 || a3
!= 0) {
545 qemu_log(TARGET_FMT_plx
": %08x %08x %08x %08x\n",
546 curaddr
, a0
, a1
, a2
, a3
);
552 LOG_MMU("No access allowed\n");
558 LOG_MMU("direct store...\n");
559 /* Direct-store segment : absolutely *BUGGY* for now */
561 /* Direct-store implies a 32-bit MMU.
562 * Check the Segment Register's bus unit ID (BUID).
564 sr
= env
->sr
[eaddr
>> 28];
565 if ((sr
& 0x1FF00000) >> 20 == 0x07f) {
566 /* Memory-forced I/O controller interface access */
567 /* If T=1 and BUID=x'07F', the 601 performs a memory access
568 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
570 ctx
->raddr
= ((sr
& 0xF) << 28) | (eaddr
& 0x0FFFFFFF);
571 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
577 /* Integer load/store : only access allowed */
580 /* No code fetch is allowed in direct-store areas */
583 /* Floating point load/store */
586 /* lwarx, ldarx or srwcx. */
589 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
590 /* Should make the instruction do no-op.
591 * As it already do no-op, it's quite easy :-)
599 qemu_log("ERROR: instruction should not need "
600 "address translation\n");
603 if ((rw
== 1 || ctx
->key
!= 1) && (rw
== 0 || ctx
->key
!= 0)) {
614 /* Generic TLB check function for embedded PowerPC implementations */
615 static int ppcemb_tlb_check(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
617 target_ulong address
, uint32_t pid
, int ext
,
622 /* Check valid flag */
623 if (!(tlb
->prot
& PAGE_VALID
)) {
626 mask
= ~(tlb
->size
- 1);
627 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx
" PID %u <=> " TARGET_FMT_lx
628 " " TARGET_FMT_lx
" %u %x\n", __func__
, i
, address
, pid
, tlb
->EPN
,
629 mask
, (uint32_t)tlb
->PID
, tlb
->prot
);
631 if (tlb
->PID
!= 0 && tlb
->PID
!= pid
) {
634 /* Check effective address */
635 if ((address
& mask
) != tlb
->EPN
) {
638 *raddrp
= (tlb
->RPN
& mask
) | (address
& ~mask
);
640 /* Extend the physical address to 36 bits */
641 *raddrp
|= (uint64_t)(tlb
->RPN
& 0xF) << 32;
647 /* Generic TLB search function for PowerPC embedded implementations */
648 static int ppcemb_tlb_search(CPUPPCState
*env
, target_ulong address
,
655 /* Default return value is no match */
657 for (i
= 0; i
< env
->nb_tlb
; i
++) {
658 tlb
= &env
->tlb
.tlbe
[i
];
659 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
, pid
, 0, i
) == 0) {
668 /* Helpers specific to PowerPC 40x implementations */
669 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState
*env
)
674 for (i
= 0; i
< env
->nb_tlb
; i
++) {
675 tlb
= &env
->tlb
.tlbe
[i
];
676 tlb
->prot
&= ~PAGE_VALID
;
681 static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState
*env
,
682 target_ulong eaddr
, uint32_t pid
)
684 #if !defined(FLUSH_ALL_TLBS)
687 target_ulong page
, end
;
690 for (i
= 0; i
< env
->nb_tlb
; i
++) {
691 tlb
= &env
->tlb
.tlbe
[i
];
692 if (ppcemb_tlb_check(env
, tlb
, &raddr
, eaddr
, pid
, 0, i
) == 0) {
693 end
= tlb
->EPN
+ tlb
->size
;
694 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
695 tlb_flush_page(env
, page
);
697 tlb
->prot
&= ~PAGE_VALID
;
702 ppc4xx_tlb_invalidate_all(env
);
706 static int mmu40x_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
707 target_ulong address
, int rw
,
712 int i
, ret
, zsel
, zpr
, pr
;
715 raddr
= (hwaddr
)-1ULL;
717 for (i
= 0; i
< env
->nb_tlb
; i
++) {
718 tlb
= &env
->tlb
.tlbe
[i
];
719 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
720 env
->spr
[SPR_40x_PID
], 0, i
) < 0) {
723 zsel
= (tlb
->attr
>> 4) & 0xF;
724 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (30 - (2 * zsel
))) & 0x3;
725 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
726 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
727 /* Check execute enable bit */
735 /* All accesses granted */
736 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
741 /* Raise Zone protection fault. */
742 env
->spr
[SPR_40x_ESR
] = 1 << 22;
750 /* Check from TLB entry */
751 ctx
->prot
= tlb
->prot
;
752 ret
= check_prot(ctx
->prot
, rw
, access_type
);
754 env
->spr
[SPR_40x_ESR
] = 0;
760 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
761 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
766 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
767 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
772 void store_40x_sler(CPUPPCState
*env
, uint32_t val
)
774 /* XXX: TO BE FIXED */
775 if (val
!= 0x00000000) {
776 cpu_abort(env
, "Little-endian regions are not supported by now\n");
778 env
->spr
[SPR_405_SLER
] = val
;
781 static inline int mmubooke_check_tlb(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
782 hwaddr
*raddr
, int *prot
,
783 target_ulong address
, int rw
,
784 int access_type
, int i
)
788 if (ppcemb_tlb_check(env
, tlb
, raddr
, address
,
789 env
->spr
[SPR_BOOKE_PID
],
790 !env
->nb_pids
, i
) >= 0) {
794 if (env
->spr
[SPR_BOOKE_PID1
] &&
795 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
796 env
->spr
[SPR_BOOKE_PID1
], 0, i
) >= 0) {
800 if (env
->spr
[SPR_BOOKE_PID2
] &&
801 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
802 env
->spr
[SPR_BOOKE_PID2
], 0, i
) >= 0) {
806 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
812 prot2
= tlb
->prot
& 0xF;
814 prot2
= (tlb
->prot
>> 4) & 0xF;
817 /* Check the address space */
818 if (access_type
== ACCESS_CODE
) {
819 if (msr_ir
!= (tlb
->attr
& 1)) {
820 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
825 if (prot2
& PAGE_EXEC
) {
826 LOG_SWTLB("%s: good TLB!\n", __func__
);
830 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
833 if (msr_dr
!= (tlb
->attr
& 1)) {
834 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
839 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
840 LOG_SWTLB("%s: found TLB!\n", __func__
);
844 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
851 static int mmubooke_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
852 target_ulong address
, int rw
,
860 raddr
= (hwaddr
)-1ULL;
861 for (i
= 0; i
< env
->nb_tlb
; i
++) {
862 tlb
= &env
->tlb
.tlbe
[i
];
863 ret
= mmubooke_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
, rw
,
872 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
873 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
876 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
877 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
883 static void booke206_flush_tlb(CPUPPCState
*env
, int flags
,
884 const int check_iprot
)
888 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
890 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
891 if (flags
& (1 << i
)) {
892 tlb_size
= booke206_tlb_size(env
, i
);
893 for (j
= 0; j
< tlb_size
; j
++) {
894 if (!check_iprot
|| !(tlb
[j
].mas1
& MAS1_IPROT
)) {
895 tlb
[j
].mas1
&= ~MAS1_VALID
;
899 tlb
+= booke206_tlb_size(env
, i
);
905 static hwaddr
booke206_tlb_to_page_size(CPUPPCState
*env
,
910 tlbm_size
= (tlb
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
912 return 1024ULL << tlbm_size
;
915 /* TLB check function for MAS based SoftTLBs */
916 static int ppcmas_tlb_check(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
918 target_ulong address
, uint32_t pid
)
923 /* Check valid flag */
924 if (!(tlb
->mas1
& MAS1_VALID
)) {
928 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
929 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx
" PID=0x%x MAS1=0x%x MAS2=0x%"
930 PRIx64
" mask=0x" TARGET_FMT_lx
" MAS7_3=0x%" PRIx64
" MAS8=%x\n",
931 __func__
, address
, pid
, tlb
->mas1
, tlb
->mas2
, mask
, tlb
->mas7_3
,
935 tlb_pid
= (tlb
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
;
936 if (tlb_pid
!= 0 && tlb_pid
!= pid
) {
940 /* Check effective address */
941 if ((address
& mask
) != (tlb
->mas2
& MAS2_EPN_MASK
)) {
946 *raddrp
= (tlb
->mas7_3
& mask
) | (address
& ~mask
);
952 static int mmubooke206_check_tlb(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
953 hwaddr
*raddr
, int *prot
,
954 target_ulong address
, int rw
,
960 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
,
961 env
->spr
[SPR_BOOKE_PID
]) >= 0) {
965 if (env
->spr
[SPR_BOOKE_PID1
] &&
966 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
967 env
->spr
[SPR_BOOKE_PID1
]) >= 0) {
971 if (env
->spr
[SPR_BOOKE_PID2
] &&
972 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
973 env
->spr
[SPR_BOOKE_PID2
]) >= 0) {
977 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
983 if (tlb
->mas7_3
& MAS3_UR
) {
986 if (tlb
->mas7_3
& MAS3_UW
) {
989 if (tlb
->mas7_3
& MAS3_UX
) {
993 if (tlb
->mas7_3
& MAS3_SR
) {
996 if (tlb
->mas7_3
& MAS3_SW
) {
999 if (tlb
->mas7_3
& MAS3_SX
) {
1004 /* Check the address space and permissions */
1005 if (access_type
== ACCESS_CODE
) {
1006 if (msr_ir
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1007 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1012 if (prot2
& PAGE_EXEC
) {
1013 LOG_SWTLB("%s: good TLB!\n", __func__
);
1017 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
1020 if (msr_dr
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1021 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1026 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
1027 LOG_SWTLB("%s: found TLB!\n", __func__
);
1031 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
1038 static int mmubooke206_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1039 target_ulong address
, int rw
,
1047 raddr
= (hwaddr
)-1ULL;
1049 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1050 int ways
= booke206_tlb_ways(env
, i
);
1052 for (j
= 0; j
< ways
; j
++) {
1053 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
1057 ret
= mmubooke206_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
,
1069 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
1070 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1073 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
1074 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
1080 static const char *book3e_tsize_to_str
[32] = {
1081 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1082 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1083 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1087 static void mmubooke_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1090 ppcemb_tlb_t
*entry
;
1093 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1094 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1098 cpu_fprintf(f
, "\nTLB:\n");
1099 cpu_fprintf(f
, "Effective Physical Size PID Prot "
1102 entry
= &env
->tlb
.tlbe
[0];
1103 for (i
= 0; i
< env
->nb_tlb
; i
++, entry
++) {
1106 uint64_t size
= (uint64_t)entry
->size
;
1109 /* Check valid flag */
1110 if (!(entry
->prot
& PAGE_VALID
)) {
1114 mask
= ~(entry
->size
- 1);
1115 ea
= entry
->EPN
& mask
;
1116 pa
= entry
->RPN
& mask
;
1117 /* Extend the physical address to 36 bits */
1118 pa
|= (hwaddr
)(entry
->RPN
& 0xF) << 32;
1121 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"M", size
/ 1024);
1123 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"k", size
);
1125 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %s %-5u %08x %08x\n",
1126 (uint64_t)ea
, (uint64_t)pa
, size_buf
, (uint32_t)entry
->PID
,
1127 entry
->prot
, entry
->attr
);
1132 static void mmubooke206_dump_one_tlb(FILE *f
, fprintf_function cpu_fprintf
,
1133 CPUPPCState
*env
, int tlbn
, int offset
,
1136 ppcmas_tlb_t
*entry
;
1139 cpu_fprintf(f
, "\nTLB%d:\n", tlbn
);
1140 cpu_fprintf(f
, "Effective Physical Size TID TS SRWX"
1141 " URWX WIMGE U0123\n");
1143 entry
= &env
->tlb
.tlbm
[offset
];
1144 for (i
= 0; i
< tlbsize
; i
++, entry
++) {
1145 hwaddr ea
, pa
, size
;
1148 if (!(entry
->mas1
& MAS1_VALID
)) {
1152 tsize
= (entry
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1153 size
= 1024ULL << tsize
;
1154 ea
= entry
->mas2
& ~(size
- 1);
1155 pa
= entry
->mas7_3
& ~(size
- 1);
1157 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %4s %-5u %1u S%c%c%c"
1158 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1159 (uint64_t)ea
, (uint64_t)pa
,
1160 book3e_tsize_to_str
[tsize
],
1161 (entry
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
,
1162 (entry
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
,
1163 entry
->mas7_3
& MAS3_SR
? 'R' : '-',
1164 entry
->mas7_3
& MAS3_SW
? 'W' : '-',
1165 entry
->mas7_3
& MAS3_SX
? 'X' : '-',
1166 entry
->mas7_3
& MAS3_UR
? 'R' : '-',
1167 entry
->mas7_3
& MAS3_UW
? 'W' : '-',
1168 entry
->mas7_3
& MAS3_UX
? 'X' : '-',
1169 entry
->mas2
& MAS2_W
? 'W' : '-',
1170 entry
->mas2
& MAS2_I
? 'I' : '-',
1171 entry
->mas2
& MAS2_M
? 'M' : '-',
1172 entry
->mas2
& MAS2_G
? 'G' : '-',
1173 entry
->mas2
& MAS2_E
? 'E' : '-',
1174 entry
->mas7_3
& MAS3_U0
? '0' : '-',
1175 entry
->mas7_3
& MAS3_U1
? '1' : '-',
1176 entry
->mas7_3
& MAS3_U2
? '2' : '-',
1177 entry
->mas7_3
& MAS3_U3
? '3' : '-');
1181 static void mmubooke206_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1187 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1188 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1192 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1193 int size
= booke206_tlb_size(env
, i
);
1199 mmubooke206_dump_one_tlb(f
, cpu_fprintf
, env
, i
, offset
, size
);
1204 void dump_mmu(FILE *f
, fprintf_function cpu_fprintf
, CPUPPCState
*env
)
1206 switch (env
->mmu_model
) {
1207 case POWERPC_MMU_BOOKE
:
1208 mmubooke_dump_mmu(f
, cpu_fprintf
, env
);
1210 case POWERPC_MMU_BOOKE206
:
1211 mmubooke206_dump_mmu(f
, cpu_fprintf
, env
);
1213 #if defined(TARGET_PPC64)
1214 case POWERPC_MMU_64B
:
1215 case POWERPC_MMU_2_06
:
1216 case POWERPC_MMU_2_06d
:
1217 dump_slb(f
, cpu_fprintf
, env
);
1221 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented\n", __func__
);
1225 static inline int check_physical(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1226 target_ulong eaddr
, int rw
)
1231 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1233 switch (env
->mmu_model
) {
1234 case POWERPC_MMU_SOFT_6xx
:
1235 case POWERPC_MMU_SOFT_74xx
:
1236 case POWERPC_MMU_SOFT_4xx
:
1237 case POWERPC_MMU_REAL
:
1238 case POWERPC_MMU_BOOKE
:
1239 ctx
->prot
|= PAGE_WRITE
;
1242 case POWERPC_MMU_SOFT_4xx_Z
:
1243 if (unlikely(msr_pe
!= 0)) {
1244 /* 403 family add some particular protections,
1245 * using PBL/PBU registers for accesses with no translation.
1248 /* Check PLB validity */
1249 (env
->pb
[0] < env
->pb
[1] &&
1250 /* and address in plb area */
1251 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1252 (env
->pb
[2] < env
->pb
[3] &&
1253 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1254 if (in_plb
^ msr_px
) {
1255 /* Access in protected area */
1257 /* Access is not allowed */
1261 /* Read-write access is allowed */
1262 ctx
->prot
|= PAGE_WRITE
;
1268 /* Caller's checks mean we should never get here for other models */
1276 static int get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1277 target_ulong eaddr
, int rw
, int access_type
)
1280 bool real_mode
= (access_type
== ACCESS_CODE
&& msr_ir
== 0)
1281 || (access_type
!= ACCESS_CODE
&& msr_dr
== 0);
1284 qemu_log("%s\n", __func__
);
1287 switch (env
->mmu_model
) {
1288 case POWERPC_MMU_SOFT_6xx
:
1289 case POWERPC_MMU_SOFT_74xx
:
1291 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1293 /* Try to find a BAT */
1294 if (env
->nb_BATs
!= 0) {
1295 ret
= get_bat_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1298 /* We didn't match any BAT entry or don't have BATs */
1299 ret
= get_segment_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1304 case POWERPC_MMU_SOFT_4xx
:
1305 case POWERPC_MMU_SOFT_4xx_Z
:
1307 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1309 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1313 case POWERPC_MMU_BOOKE
:
1314 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1317 case POWERPC_MMU_BOOKE206
:
1318 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1321 case POWERPC_MMU_MPC8xx
:
1323 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1325 case POWERPC_MMU_REAL
:
1327 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1329 cpu_abort(env
, "PowerPC in real mode do not do any translation\n");
1333 cpu_abort(env
, "Unknown or invalid MMU model\n");
1337 qemu_log("%s address " TARGET_FMT_lx
" => %d " TARGET_FMT_plx
"\n",
1338 __func__
, eaddr
, ret
, ctx
->raddr
);
1344 hwaddr
cpu_get_phys_page_debug(CPUPPCState
*env
, target_ulong addr
)
1348 switch (env
->mmu_model
) {
1349 #if defined(TARGET_PPC64)
1350 case POWERPC_MMU_64B
:
1351 case POWERPC_MMU_2_06
:
1352 case POWERPC_MMU_2_06d
:
1353 return ppc_hash64_get_phys_page_debug(env
, addr
);
1356 case POWERPC_MMU_32B
:
1357 case POWERPC_MMU_601
:
1358 return ppc_hash32_get_phys_page_debug(env
, addr
);
1364 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0)) {
1368 return ctx
.raddr
& TARGET_PAGE_MASK
;
1371 static void booke206_update_mas_tlb_miss(CPUPPCState
*env
, target_ulong address
,
1374 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
1375 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
1376 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
1377 env
->spr
[SPR_BOOKE_MAS3
] = 0;
1378 env
->spr
[SPR_BOOKE_MAS6
] = 0;
1379 env
->spr
[SPR_BOOKE_MAS7
] = 0;
1382 if (((rw
== 2) && msr_ir
) || ((rw
!= 2) && msr_dr
)) {
1383 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
1384 env
->spr
[SPR_BOOKE_MAS6
] |= MAS6_SAS
;
1387 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_VALID
;
1388 env
->spr
[SPR_BOOKE_MAS2
] |= address
& MAS2_EPN_MASK
;
1390 switch (env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TIDSELD_PIDZ
) {
1391 case MAS4_TIDSELD_PID0
:
1392 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID
] << MAS1_TID_SHIFT
;
1394 case MAS4_TIDSELD_PID1
:
1395 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID1
] << MAS1_TID_SHIFT
;
1397 case MAS4_TIDSELD_PID2
:
1398 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID2
] << MAS1_TID_SHIFT
;
1402 env
->spr
[SPR_BOOKE_MAS6
] |= env
->spr
[SPR_BOOKE_PID
] << 16;
1404 /* next victim logic */
1405 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
1407 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
1408 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
1411 /* Perform address translation */
1412 int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
, int rw
,
1419 switch (env
->mmu_model
) {
1420 #if defined(TARGET_PPC64)
1421 case POWERPC_MMU_64B
:
1422 case POWERPC_MMU_2_06
:
1423 case POWERPC_MMU_2_06d
:
1424 return ppc_hash64_handle_mmu_fault(env
, address
, rw
, mmu_idx
);
1427 case POWERPC_MMU_32B
:
1428 case POWERPC_MMU_601
:
1429 return ppc_hash32_handle_mmu_fault(env
, address
, rw
, mmu_idx
);
1432 ; /* Otherwise fall through to the general code below */
1438 access_type
= ACCESS_CODE
;
1441 access_type
= env
->access_type
;
1443 ret
= get_physical_address(env
, &ctx
, address
, rw
, access_type
);
1445 tlb_set_page(env
, address
& TARGET_PAGE_MASK
,
1446 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1447 mmu_idx
, TARGET_PAGE_SIZE
);
1449 } else if (ret
< 0) {
1451 if (access_type
== ACCESS_CODE
) {
1454 /* No matches in page tables or TLB */
1455 switch (env
->mmu_model
) {
1456 case POWERPC_MMU_SOFT_6xx
:
1457 env
->exception_index
= POWERPC_EXCP_IFTLB
;
1458 env
->error_code
= 1 << 18;
1459 env
->spr
[SPR_IMISS
] = address
;
1460 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1462 case POWERPC_MMU_SOFT_74xx
:
1463 env
->exception_index
= POWERPC_EXCP_IFTLB
;
1465 case POWERPC_MMU_SOFT_4xx
:
1466 case POWERPC_MMU_SOFT_4xx_Z
:
1467 env
->exception_index
= POWERPC_EXCP_ITLB
;
1468 env
->error_code
= 0;
1469 env
->spr
[SPR_40x_DEAR
] = address
;
1470 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1472 case POWERPC_MMU_BOOKE206
:
1473 booke206_update_mas_tlb_miss(env
, address
, rw
);
1475 case POWERPC_MMU_BOOKE
:
1476 env
->exception_index
= POWERPC_EXCP_ITLB
;
1477 env
->error_code
= 0;
1478 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1480 case POWERPC_MMU_MPC8xx
:
1482 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1484 case POWERPC_MMU_REAL
:
1485 cpu_abort(env
, "PowerPC in real mode should never raise "
1486 "any MMU exceptions\n");
1489 cpu_abort(env
, "Unknown or invalid MMU model\n");
1494 /* Access rights violation */
1495 env
->exception_index
= POWERPC_EXCP_ISI
;
1496 env
->error_code
= 0x08000000;
1499 /* No execute protection violation */
1500 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1501 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1502 env
->spr
[SPR_BOOKE_ESR
] = 0x00000000;
1504 env
->exception_index
= POWERPC_EXCP_ISI
;
1505 env
->error_code
= 0x10000000;
1508 /* Direct store exception */
1509 /* No code fetch is allowed in direct-store areas */
1510 env
->exception_index
= POWERPC_EXCP_ISI
;
1511 env
->error_code
= 0x10000000;
1517 /* No matches in page tables or TLB */
1518 switch (env
->mmu_model
) {
1519 case POWERPC_MMU_SOFT_6xx
:
1521 env
->exception_index
= POWERPC_EXCP_DSTLB
;
1522 env
->error_code
= 1 << 16;
1524 env
->exception_index
= POWERPC_EXCP_DLTLB
;
1525 env
->error_code
= 0;
1527 env
->spr
[SPR_DMISS
] = address
;
1528 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1530 env
->error_code
|= ctx
.key
<< 19;
1531 env
->spr
[SPR_HASH1
] = env
->htab_base
+
1532 get_pteg_offset32(env
, ctx
.hash
[0]);
1533 env
->spr
[SPR_HASH2
] = env
->htab_base
+
1534 get_pteg_offset32(env
, ctx
.hash
[1]);
1536 case POWERPC_MMU_SOFT_74xx
:
1538 env
->exception_index
= POWERPC_EXCP_DSTLB
;
1540 env
->exception_index
= POWERPC_EXCP_DLTLB
;
1543 /* Implement LRU algorithm */
1544 env
->error_code
= ctx
.key
<< 19;
1545 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1546 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1547 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1549 case POWERPC_MMU_SOFT_4xx
:
1550 case POWERPC_MMU_SOFT_4xx_Z
:
1551 env
->exception_index
= POWERPC_EXCP_DTLB
;
1552 env
->error_code
= 0;
1553 env
->spr
[SPR_40x_DEAR
] = address
;
1555 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1557 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1560 case POWERPC_MMU_MPC8xx
:
1562 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1564 case POWERPC_MMU_BOOKE206
:
1565 booke206_update_mas_tlb_miss(env
, address
, rw
);
1567 case POWERPC_MMU_BOOKE
:
1568 env
->exception_index
= POWERPC_EXCP_DTLB
;
1569 env
->error_code
= 0;
1570 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1571 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1573 case POWERPC_MMU_REAL
:
1574 cpu_abort(env
, "PowerPC in real mode should never raise "
1575 "any MMU exceptions\n");
1578 cpu_abort(env
, "Unknown or invalid MMU model\n");
1583 /* Access rights violation */
1584 env
->exception_index
= POWERPC_EXCP_DSI
;
1585 env
->error_code
= 0;
1586 if (env
->mmu_model
== POWERPC_MMU_SOFT_4xx
1587 || env
->mmu_model
== POWERPC_MMU_SOFT_4xx_Z
) {
1588 env
->spr
[SPR_40x_DEAR
] = address
;
1590 env
->spr
[SPR_40x_ESR
] |= 0x00800000;
1592 } else if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1593 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1594 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1595 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1597 env
->spr
[SPR_DAR
] = address
;
1599 env
->spr
[SPR_DSISR
] = 0x0A000000;
1601 env
->spr
[SPR_DSISR
] = 0x08000000;
1606 /* Direct store exception */
1607 switch (access_type
) {
1609 /* Floating point load/store */
1610 env
->exception_index
= POWERPC_EXCP_ALIGN
;
1611 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1612 env
->spr
[SPR_DAR
] = address
;
1615 /* lwarx, ldarx or stwcx. */
1616 env
->exception_index
= POWERPC_EXCP_DSI
;
1617 env
->error_code
= 0;
1618 env
->spr
[SPR_DAR
] = address
;
1620 env
->spr
[SPR_DSISR
] = 0x06000000;
1622 env
->spr
[SPR_DSISR
] = 0x04000000;
1626 /* eciwx or ecowx */
1627 env
->exception_index
= POWERPC_EXCP_DSI
;
1628 env
->error_code
= 0;
1629 env
->spr
[SPR_DAR
] = address
;
1631 env
->spr
[SPR_DSISR
] = 0x06100000;
1633 env
->spr
[SPR_DSISR
] = 0x04100000;
1637 printf("DSI: invalid exception (%d)\n", ret
);
1638 env
->exception_index
= POWERPC_EXCP_PROGRAM
;
1640 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1641 env
->spr
[SPR_DAR
] = address
;
1648 printf("%s: set exception to %d %02x\n", __func__
,
1649 env
->exception
, env
->error_code
);
1657 /*****************************************************************************/
1658 /* BATs management */
1659 #if !defined(FLUSH_ALL_TLBS)
1660 static inline void do_invalidate_BAT(CPUPPCState
*env
, target_ulong BATu
,
1663 target_ulong base
, end
, page
;
1665 base
= BATu
& ~0x0001FFFF;
1666 end
= base
+ mask
+ 0x00020000;
1667 LOG_BATS("Flush BAT from " TARGET_FMT_lx
" to " TARGET_FMT_lx
" ("
1668 TARGET_FMT_lx
")\n", base
, end
, mask
);
1669 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
1670 tlb_flush_page(env
, page
);
1672 LOG_BATS("Flush done\n");
1676 static inline void dump_store_bat(CPUPPCState
*env
, char ID
, int ul
, int nr
,
1679 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx
" (" TARGET_FMT_lx
")\n", ID
,
1680 nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1683 void helper_store_ibatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1687 dump_store_bat(env
, 'I', 0, nr
, value
);
1688 if (env
->IBAT
[0][nr
] != value
) {
1689 mask
= (value
<< 15) & 0x0FFE0000UL
;
1690 #if !defined(FLUSH_ALL_TLBS)
1691 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1693 /* When storing valid upper BAT, mask BEPI and BRPN
1694 * and invalidate all TLBs covered by this BAT
1696 mask
= (value
<< 15) & 0x0FFE0000UL
;
1697 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1698 (value
& ~0x0001FFFFUL
& ~mask
);
1699 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1700 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1701 #if !defined(FLUSH_ALL_TLBS)
1702 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1709 void helper_store_ibatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1711 dump_store_bat(env
, 'I', 1, nr
, value
);
1712 env
->IBAT
[1][nr
] = value
;
1715 void helper_store_dbatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1719 dump_store_bat(env
, 'D', 0, nr
, value
);
1720 if (env
->DBAT
[0][nr
] != value
) {
1721 /* When storing valid upper BAT, mask BEPI and BRPN
1722 * and invalidate all TLBs covered by this BAT
1724 mask
= (value
<< 15) & 0x0FFE0000UL
;
1725 #if !defined(FLUSH_ALL_TLBS)
1726 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1728 mask
= (value
<< 15) & 0x0FFE0000UL
;
1729 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1730 (value
& ~0x0001FFFFUL
& ~mask
);
1731 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1732 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1733 #if !defined(FLUSH_ALL_TLBS)
1734 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1741 void helper_store_dbatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1743 dump_store_bat(env
, 'D', 1, nr
, value
);
1744 env
->DBAT
[1][nr
] = value
;
1747 void helper_store_601_batu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1750 #if defined(FLUSH_ALL_TLBS)
1754 dump_store_bat(env
, 'I', 0, nr
, value
);
1755 if (env
->IBAT
[0][nr
] != value
) {
1756 #if defined(FLUSH_ALL_TLBS)
1759 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1760 if (env
->IBAT
[1][nr
] & 0x40) {
1761 /* Invalidate BAT only if it is valid */
1762 #if !defined(FLUSH_ALL_TLBS)
1763 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1768 /* When storing valid upper BAT, mask BEPI and BRPN
1769 * and invalidate all TLBs covered by this BAT
1771 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1772 (value
& ~0x0001FFFFUL
& ~mask
);
1773 env
->DBAT
[0][nr
] = env
->IBAT
[0][nr
];
1774 if (env
->IBAT
[1][nr
] & 0x40) {
1775 #if !defined(FLUSH_ALL_TLBS)
1776 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1781 #if defined(FLUSH_ALL_TLBS)
1789 void helper_store_601_batl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1791 #if !defined(FLUSH_ALL_TLBS)
1797 dump_store_bat(env
, 'I', 1, nr
, value
);
1798 if (env
->IBAT
[1][nr
] != value
) {
1799 #if defined(FLUSH_ALL_TLBS)
1802 if (env
->IBAT
[1][nr
] & 0x40) {
1803 #if !defined(FLUSH_ALL_TLBS)
1804 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1805 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1811 #if !defined(FLUSH_ALL_TLBS)
1812 mask
= (value
<< 17) & 0x0FFE0000UL
;
1813 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1818 env
->IBAT
[1][nr
] = value
;
1819 env
->DBAT
[1][nr
] = value
;
1820 #if defined(FLUSH_ALL_TLBS)
1828 /*****************************************************************************/
1829 /* TLB management */
1830 void ppc_tlb_invalidate_all(CPUPPCState
*env
)
1832 switch (env
->mmu_model
) {
1833 case POWERPC_MMU_SOFT_6xx
:
1834 case POWERPC_MMU_SOFT_74xx
:
1835 ppc6xx_tlb_invalidate_all(env
);
1837 case POWERPC_MMU_SOFT_4xx
:
1838 case POWERPC_MMU_SOFT_4xx_Z
:
1839 ppc4xx_tlb_invalidate_all(env
);
1841 case POWERPC_MMU_REAL
:
1842 cpu_abort(env
, "No TLB for PowerPC 4xx in real mode\n");
1844 case POWERPC_MMU_MPC8xx
:
1846 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1848 case POWERPC_MMU_BOOKE
:
1851 case POWERPC_MMU_BOOKE206
:
1852 booke206_flush_tlb(env
, -1, 0);
1854 case POWERPC_MMU_32B
:
1855 case POWERPC_MMU_601
:
1856 #if defined(TARGET_PPC64)
1857 case POWERPC_MMU_64B
:
1858 case POWERPC_MMU_2_06
:
1859 case POWERPC_MMU_2_06d
:
1860 #endif /* defined(TARGET_PPC64) */
1865 cpu_abort(env
, "Unknown MMU model\n");
1870 void ppc_tlb_invalidate_one(CPUPPCState
*env
, target_ulong addr
)
1872 #if !defined(FLUSH_ALL_TLBS)
1873 addr
&= TARGET_PAGE_MASK
;
1874 switch (env
->mmu_model
) {
1875 case POWERPC_MMU_SOFT_6xx
:
1876 case POWERPC_MMU_SOFT_74xx
:
1877 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
1878 if (env
->id_tlbs
== 1) {
1879 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
1882 case POWERPC_MMU_SOFT_4xx
:
1883 case POWERPC_MMU_SOFT_4xx_Z
:
1884 ppc4xx_tlb_invalidate_virt(env
, addr
, env
->spr
[SPR_40x_PID
]);
1886 case POWERPC_MMU_REAL
:
1887 cpu_abort(env
, "No TLB for PowerPC 4xx in real mode\n");
1889 case POWERPC_MMU_MPC8xx
:
1891 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1893 case POWERPC_MMU_BOOKE
:
1895 cpu_abort(env
, "BookE MMU model is not implemented\n");
1897 case POWERPC_MMU_BOOKE206
:
1899 cpu_abort(env
, "BookE 2.06 MMU model is not implemented\n");
1901 case POWERPC_MMU_32B
:
1902 case POWERPC_MMU_601
:
1903 /* tlbie invalidate TLBs for all segments */
1904 addr
&= ~((target_ulong
)-1ULL << 28);
1905 /* XXX: this case should be optimized,
1906 * giving a mask to tlb_flush_page
1908 tlb_flush_page(env
, addr
| (0x0 << 28));
1909 tlb_flush_page(env
, addr
| (0x1 << 28));
1910 tlb_flush_page(env
, addr
| (0x2 << 28));
1911 tlb_flush_page(env
, addr
| (0x3 << 28));
1912 tlb_flush_page(env
, addr
| (0x4 << 28));
1913 tlb_flush_page(env
, addr
| (0x5 << 28));
1914 tlb_flush_page(env
, addr
| (0x6 << 28));
1915 tlb_flush_page(env
, addr
| (0x7 << 28));
1916 tlb_flush_page(env
, addr
| (0x8 << 28));
1917 tlb_flush_page(env
, addr
| (0x9 << 28));
1918 tlb_flush_page(env
, addr
| (0xA << 28));
1919 tlb_flush_page(env
, addr
| (0xB << 28));
1920 tlb_flush_page(env
, addr
| (0xC << 28));
1921 tlb_flush_page(env
, addr
| (0xD << 28));
1922 tlb_flush_page(env
, addr
| (0xE << 28));
1923 tlb_flush_page(env
, addr
| (0xF << 28));
1925 #if defined(TARGET_PPC64)
1926 case POWERPC_MMU_64B
:
1927 case POWERPC_MMU_2_06
:
1928 case POWERPC_MMU_2_06d
:
1929 /* tlbie invalidate TLBs for all segments */
1930 /* XXX: given the fact that there are too many segments to invalidate,
1931 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
1932 * we just invalidate all TLBs
1936 #endif /* defined(TARGET_PPC64) */
1939 cpu_abort(env
, "Unknown MMU model\n");
1943 ppc_tlb_invalidate_all(env
);
1947 /*****************************************************************************/
1948 /* Special registers manipulation */
1949 void ppc_store_sdr1(CPUPPCState
*env
, target_ulong value
)
1951 LOG_MMU("%s: " TARGET_FMT_lx
"\n", __func__
, value
);
1952 if (env
->spr
[SPR_SDR1
] != value
) {
1953 env
->spr
[SPR_SDR1
] = value
;
1954 #if defined(TARGET_PPC64)
1955 if (env
->mmu_model
& POWERPC_MMU_64
) {
1956 target_ulong htabsize
= value
& SDR_64_HTABSIZE
;
1958 if (htabsize
> 28) {
1959 fprintf(stderr
, "Invalid HTABSIZE 0x" TARGET_FMT_lx
1960 " stored in SDR1\n", htabsize
);
1963 env
->htab_mask
= (1ULL << (htabsize
+ 18)) - 1;
1964 env
->htab_base
= value
& SDR_64_HTABORG
;
1966 #endif /* defined(TARGET_PPC64) */
1968 /* FIXME: Should check for valid HTABMASK values */
1969 env
->htab_mask
= ((value
& SDR_32_HTABMASK
) << 16) | 0xFFFF;
1970 env
->htab_base
= value
& SDR_32_HTABORG
;
1976 /* Segment registers load and store */
1977 target_ulong
helper_load_sr(CPUPPCState
*env
, target_ulong sr_num
)
1979 #if defined(TARGET_PPC64)
1980 if (env
->mmu_model
& POWERPC_MMU_64
) {
1985 return env
->sr
[sr_num
];
1988 void helper_store_sr(CPUPPCState
*env
, target_ulong srnum
, target_ulong value
)
1990 LOG_MMU("%s: reg=%d " TARGET_FMT_lx
" " TARGET_FMT_lx
"\n", __func__
,
1991 (int)srnum
, value
, env
->sr
[srnum
]);
1992 #if defined(TARGET_PPC64)
1993 if (env
->mmu_model
& POWERPC_MMU_64
) {
1994 uint64_t rb
= 0, rs
= 0;
1997 rb
|= ((uint32_t)srnum
& 0xf) << 28;
1998 /* Set the valid bit */
2001 rb
|= (uint32_t)srnum
;
2004 rs
|= (value
& 0xfffffff) << 12;
2006 rs
|= ((value
>> 27) & 0xf) << 8;
2008 ppc_store_slb(env
, rb
, rs
);
2011 if (env
->sr
[srnum
] != value
) {
2012 env
->sr
[srnum
] = value
;
2013 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2014 flusing the whole TLB. */
2015 #if !defined(FLUSH_ALL_TLBS) && 0
2017 target_ulong page
, end
;
2018 /* Invalidate 256 MB of virtual memory */
2019 page
= (16 << 20) * srnum
;
2020 end
= page
+ (16 << 20);
2021 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
2022 tlb_flush_page(env
, page
);
2030 #endif /* !defined(CONFIG_USER_ONLY) */
2032 #if !defined(CONFIG_USER_ONLY)
2033 /* TLB management */
2034 void helper_tlbia(CPUPPCState
*env
)
2036 ppc_tlb_invalidate_all(env
);
2039 void helper_tlbie(CPUPPCState
*env
, target_ulong addr
)
2041 ppc_tlb_invalidate_one(env
, addr
);
2044 /* Software driven TLBs management */
2045 /* PowerPC 602/603 software TLB load instructions helpers */
2046 static void do_6xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2048 target_ulong RPN
, CMP
, EPN
;
2051 RPN
= env
->spr
[SPR_RPA
];
2053 CMP
= env
->spr
[SPR_ICMP
];
2054 EPN
= env
->spr
[SPR_IMISS
];
2056 CMP
= env
->spr
[SPR_DCMP
];
2057 EPN
= env
->spr
[SPR_DMISS
];
2059 way
= (env
->spr
[SPR_SRR1
] >> 17) & 1;
2060 (void)EPN
; /* avoid a compiler warning */
2061 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2062 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2064 /* Store this TLB */
2065 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2066 way
, is_code
, CMP
, RPN
);
2069 void helper_6xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2071 do_6xx_tlb(env
, EPN
, 0);
2074 void helper_6xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2076 do_6xx_tlb(env
, EPN
, 1);
2079 /* PowerPC 74xx software TLB load instructions helpers */
2080 static void do_74xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2082 target_ulong RPN
, CMP
, EPN
;
2085 RPN
= env
->spr
[SPR_PTELO
];
2086 CMP
= env
->spr
[SPR_PTEHI
];
2087 EPN
= env
->spr
[SPR_TLBMISS
] & ~0x3;
2088 way
= env
->spr
[SPR_TLBMISS
] & 0x3;
2089 (void)EPN
; /* avoid a compiler warning */
2090 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2091 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2093 /* Store this TLB */
2094 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2095 way
, is_code
, CMP
, RPN
);
2098 void helper_74xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2100 do_74xx_tlb(env
, EPN
, 0);
2103 void helper_74xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2105 do_74xx_tlb(env
, EPN
, 1);
2108 /*****************************************************************************/
2109 /* PowerPC 601 specific instructions (POWER bridge) */
2111 target_ulong
helper_rac(CPUPPCState
*env
, target_ulong addr
)
2115 target_ulong ret
= 0;
2117 /* We don't have to generate many instances of this instruction,
2118 * as rac is supervisor only.
2120 /* XXX: FIX THIS: Pretend we have no BAT */
2121 nb_BATs
= env
->nb_BATs
;
2123 if (get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) == 0) {
2126 env
->nb_BATs
= nb_BATs
;
2130 static inline target_ulong
booke_tlb_to_page_size(int size
)
2132 return 1024 << (2 * size
);
2135 static inline int booke_page_size_to_tlb(target_ulong page_size
)
2139 switch (page_size
) {
2173 #if defined(TARGET_PPC64)
2174 case 0x000100000000ULL
:
2177 case 0x000400000000ULL
:
2180 case 0x001000000000ULL
:
2183 case 0x004000000000ULL
:
2186 case 0x010000000000ULL
:
2198 /* Helpers for 4xx TLB management */
2199 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2201 #define PPC4XX_TLBHI_V 0x00000040
2202 #define PPC4XX_TLBHI_E 0x00000020
2203 #define PPC4XX_TLBHI_SIZE_MIN 0
2204 #define PPC4XX_TLBHI_SIZE_MAX 7
2205 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2206 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2207 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2209 #define PPC4XX_TLBLO_EX 0x00000200
2210 #define PPC4XX_TLBLO_WR 0x00000100
2211 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2212 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2214 target_ulong
helper_4xx_tlbre_hi(CPUPPCState
*env
, target_ulong entry
)
2220 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2221 tlb
= &env
->tlb
.tlbe
[entry
];
2223 if (tlb
->prot
& PAGE_VALID
) {
2224 ret
|= PPC4XX_TLBHI_V
;
2226 size
= booke_page_size_to_tlb(tlb
->size
);
2227 if (size
< PPC4XX_TLBHI_SIZE_MIN
|| size
> PPC4XX_TLBHI_SIZE_MAX
) {
2228 size
= PPC4XX_TLBHI_SIZE_DEFAULT
;
2230 ret
|= size
<< PPC4XX_TLBHI_SIZE_SHIFT
;
2231 env
->spr
[SPR_40x_PID
] = tlb
->PID
;
2235 target_ulong
helper_4xx_tlbre_lo(CPUPPCState
*env
, target_ulong entry
)
2240 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2241 tlb
= &env
->tlb
.tlbe
[entry
];
2243 if (tlb
->prot
& PAGE_EXEC
) {
2244 ret
|= PPC4XX_TLBLO_EX
;
2246 if (tlb
->prot
& PAGE_WRITE
) {
2247 ret
|= PPC4XX_TLBLO_WR
;
2252 void helper_4xx_tlbwe_hi(CPUPPCState
*env
, target_ulong entry
,
2256 target_ulong page
, end
;
2258 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2260 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2261 tlb
= &env
->tlb
.tlbe
[entry
];
2262 /* Invalidate previous TLB (if it's valid) */
2263 if (tlb
->prot
& PAGE_VALID
) {
2264 end
= tlb
->EPN
+ tlb
->size
;
2265 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx
" end "
2266 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2267 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2268 tlb_flush_page(env
, page
);
2271 tlb
->size
= booke_tlb_to_page_size((val
>> PPC4XX_TLBHI_SIZE_SHIFT
)
2272 & PPC4XX_TLBHI_SIZE_MASK
);
2273 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2274 * If this ever occurs, one should use the ppcemb target instead
2275 * of the ppc or ppc64 one
2277 if ((val
& PPC4XX_TLBHI_V
) && tlb
->size
< TARGET_PAGE_SIZE
) {
2278 cpu_abort(env
, "TLB size " TARGET_FMT_lu
" < %u "
2279 "are not supported (%d)\n",
2280 tlb
->size
, TARGET_PAGE_SIZE
, (int)((val
>> 7) & 0x7));
2282 tlb
->EPN
= val
& ~(tlb
->size
- 1);
2283 if (val
& PPC4XX_TLBHI_V
) {
2284 tlb
->prot
|= PAGE_VALID
;
2285 if (val
& PPC4XX_TLBHI_E
) {
2286 /* XXX: TO BE FIXED */
2288 "Little-endian TLB entries are not supported by now\n");
2291 tlb
->prot
&= ~PAGE_VALID
;
2293 tlb
->PID
= env
->spr
[SPR_40x_PID
]; /* PID */
2294 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2295 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2296 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2297 tlb
->prot
& PAGE_READ
? 'r' : '-',
2298 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2299 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2300 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2301 /* Invalidate new TLB (if valid) */
2302 if (tlb
->prot
& PAGE_VALID
) {
2303 end
= tlb
->EPN
+ tlb
->size
;
2304 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx
" end "
2305 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2306 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2307 tlb_flush_page(env
, page
);
2312 void helper_4xx_tlbwe_lo(CPUPPCState
*env
, target_ulong entry
,
2317 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2319 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2320 tlb
= &env
->tlb
.tlbe
[entry
];
2321 tlb
->attr
= val
& PPC4XX_TLBLO_ATTR_MASK
;
2322 tlb
->RPN
= val
& PPC4XX_TLBLO_RPN_MASK
;
2323 tlb
->prot
= PAGE_READ
;
2324 if (val
& PPC4XX_TLBLO_EX
) {
2325 tlb
->prot
|= PAGE_EXEC
;
2327 if (val
& PPC4XX_TLBLO_WR
) {
2328 tlb
->prot
|= PAGE_WRITE
;
2330 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2331 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2332 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2333 tlb
->prot
& PAGE_READ
? 'r' : '-',
2334 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2335 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2336 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2339 target_ulong
helper_4xx_tlbsx(CPUPPCState
*env
, target_ulong address
)
2341 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_40x_PID
]);
2344 /* PowerPC 440 TLB management */
2345 void helper_440_tlbwe(CPUPPCState
*env
, uint32_t word
, target_ulong entry
,
2349 target_ulong EPN
, RPN
, size
;
2352 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx
"\n",
2353 __func__
, word
, (int)entry
, value
);
2356 tlb
= &env
->tlb
.tlbe
[entry
];
2359 /* Just here to please gcc */
2361 EPN
= value
& 0xFFFFFC00;
2362 if ((tlb
->prot
& PAGE_VALID
) && EPN
!= tlb
->EPN
) {
2366 size
= booke_tlb_to_page_size((value
>> 4) & 0xF);
2367 if ((tlb
->prot
& PAGE_VALID
) && tlb
->size
< size
) {
2372 tlb
->attr
|= (value
>> 8) & 1;
2373 if (value
& 0x200) {
2374 tlb
->prot
|= PAGE_VALID
;
2376 if (tlb
->prot
& PAGE_VALID
) {
2377 tlb
->prot
&= ~PAGE_VALID
;
2381 tlb
->PID
= env
->spr
[SPR_440_MMUCR
] & 0x000000FF;
2382 if (do_flush_tlbs
) {
2387 RPN
= value
& 0xFFFFFC0F;
2388 if ((tlb
->prot
& PAGE_VALID
) && tlb
->RPN
!= RPN
) {
2394 tlb
->attr
= (tlb
->attr
& 0x1) | (value
& 0x0000FF00);
2395 tlb
->prot
= tlb
->prot
& PAGE_VALID
;
2397 tlb
->prot
|= PAGE_READ
<< 4;
2400 tlb
->prot
|= PAGE_WRITE
<< 4;
2403 tlb
->prot
|= PAGE_EXEC
<< 4;
2406 tlb
->prot
|= PAGE_READ
;
2409 tlb
->prot
|= PAGE_WRITE
;
2412 tlb
->prot
|= PAGE_EXEC
;
2418 target_ulong
helper_440_tlbre(CPUPPCState
*env
, uint32_t word
,
2426 tlb
= &env
->tlb
.tlbe
[entry
];
2429 /* Just here to please gcc */
2432 size
= booke_page_size_to_tlb(tlb
->size
);
2433 if (size
< 0 || size
> 0xF) {
2437 if (tlb
->attr
& 0x1) {
2440 if (tlb
->prot
& PAGE_VALID
) {
2443 env
->spr
[SPR_440_MMUCR
] &= ~0x000000FF;
2444 env
->spr
[SPR_440_MMUCR
] |= tlb
->PID
;
2450 ret
= tlb
->attr
& ~0x1;
2451 if (tlb
->prot
& (PAGE_READ
<< 4)) {
2454 if (tlb
->prot
& (PAGE_WRITE
<< 4)) {
2457 if (tlb
->prot
& (PAGE_EXEC
<< 4)) {
2460 if (tlb
->prot
& PAGE_READ
) {
2463 if (tlb
->prot
& PAGE_WRITE
) {
2466 if (tlb
->prot
& PAGE_EXEC
) {
2474 target_ulong
helper_440_tlbsx(CPUPPCState
*env
, target_ulong address
)
2476 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_440_MMUCR
] & 0xFF);
2479 /* PowerPC BookE 2.06 TLB management */
2481 static ppcmas_tlb_t
*booke206_cur_tlb(CPUPPCState
*env
)
2483 uint32_t tlbncfg
= 0;
2484 int esel
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ESEL_MASK
) >> MAS0_ESEL_SHIFT
;
2485 int ea
= (env
->spr
[SPR_BOOKE_MAS2
] & MAS2_EPN_MASK
);
2488 tlb
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2489 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlb
];
2491 if ((tlbncfg
& TLBnCFG_HES
) && (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_HES
)) {
2492 cpu_abort(env
, "we don't support HES yet\n");
2495 return booke206_get_tlbm(env
, tlb
, ea
, esel
);
2498 void helper_booke_setpid(CPUPPCState
*env
, uint32_t pidn
, target_ulong pid
)
2500 env
->spr
[pidn
] = pid
;
2501 /* changing PIDs mean we're in a different address space now */
2505 void helper_booke206_tlbwe(CPUPPCState
*env
)
2507 uint32_t tlbncfg
, tlbn
;
2509 uint32_t size_tlb
, size_ps
;
2513 switch (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_WQ_MASK
) {
2514 case MAS0_WQ_ALWAYS
:
2515 /* good to go, write that entry */
2518 /* XXX check if reserved */
2523 case MAS0_WQ_CLR_RSRV
:
2524 /* XXX clear entry */
2527 /* no idea what to do */
2531 if (((env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ATSEL
) == MAS0_ATSEL_LRAT
) &&
2533 /* XXX we don't support direct LRAT setting yet */
2534 fprintf(stderr
, "cpu: don't support LRAT setting yet\n");
2538 tlbn
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2539 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlbn
];
2541 tlb
= booke206_cur_tlb(env
);
2544 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2545 POWERPC_EXCP_INVAL
|
2546 POWERPC_EXCP_INVAL_INVAL
);
2549 /* check that we support the targeted size */
2550 size_tlb
= (env
->spr
[SPR_BOOKE_MAS1
] & MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
2551 size_ps
= booke206_tlbnps(env
, tlbn
);
2552 if ((env
->spr
[SPR_BOOKE_MAS1
] & MAS1_VALID
) && (tlbncfg
& TLBnCFG_AVAIL
) &&
2553 !(size_ps
& (1 << size_tlb
))) {
2554 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2555 POWERPC_EXCP_INVAL
|
2556 POWERPC_EXCP_INVAL_INVAL
);
2560 cpu_abort(env
, "missing HV implementation\n");
2562 tlb
->mas7_3
= ((uint64_t)env
->spr
[SPR_BOOKE_MAS7
] << 32) |
2563 env
->spr
[SPR_BOOKE_MAS3
];
2564 tlb
->mas1
= env
->spr
[SPR_BOOKE_MAS1
];
2567 if (!(tlbncfg
& TLBnCFG_AVAIL
)) {
2568 /* force !AVAIL TLB entries to correct page size */
2569 tlb
->mas1
&= ~MAS1_TSIZE_MASK
;
2570 /* XXX can be configured in MMUCSR0 */
2571 tlb
->mas1
|= (tlbncfg
& TLBnCFG_MINSIZE
) >> 12;
2574 /* Make a mask from TLB size to discard invalid bits in EPN field */
2575 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2576 /* Add a mask for page attributes */
2577 mask
|= MAS2_ACM
| MAS2_VLE
| MAS2_W
| MAS2_I
| MAS2_M
| MAS2_G
| MAS2_E
;
2580 /* Executing a tlbwe instruction in 32-bit mode will set
2581 * bits 0:31 of the TLB EPN field to zero.
2586 tlb
->mas2
= env
->spr
[SPR_BOOKE_MAS2
] & mask
;
2588 if (!(tlbncfg
& TLBnCFG_IPROT
)) {
2589 /* no IPROT supported by TLB */
2590 tlb
->mas1
&= ~MAS1_IPROT
;
2593 if (booke206_tlb_to_page_size(env
, tlb
) == TARGET_PAGE_SIZE
) {
2594 tlb_flush_page(env
, tlb
->mas2
& MAS2_EPN_MASK
);
2600 static inline void booke206_tlb_to_mas(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2602 int tlbn
= booke206_tlbm_to_tlbn(env
, tlb
);
2603 int way
= booke206_tlbm_to_way(env
, tlb
);
2605 env
->spr
[SPR_BOOKE_MAS0
] = tlbn
<< MAS0_TLBSEL_SHIFT
;
2606 env
->spr
[SPR_BOOKE_MAS0
] |= way
<< MAS0_ESEL_SHIFT
;
2607 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2609 env
->spr
[SPR_BOOKE_MAS1
] = tlb
->mas1
;
2610 env
->spr
[SPR_BOOKE_MAS2
] = tlb
->mas2
;
2611 env
->spr
[SPR_BOOKE_MAS3
] = tlb
->mas7_3
;
2612 env
->spr
[SPR_BOOKE_MAS7
] = tlb
->mas7_3
>> 32;
2615 void helper_booke206_tlbre(CPUPPCState
*env
)
2617 ppcmas_tlb_t
*tlb
= NULL
;
2619 tlb
= booke206_cur_tlb(env
);
2621 env
->spr
[SPR_BOOKE_MAS1
] = 0;
2623 booke206_tlb_to_mas(env
, tlb
);
2627 void helper_booke206_tlbsx(CPUPPCState
*env
, target_ulong address
)
2629 ppcmas_tlb_t
*tlb
= NULL
;
2634 spid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID_MASK
) >> MAS6_SPID_SHIFT
;
2635 sas
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
;
2637 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2638 int ways
= booke206_tlb_ways(env
, i
);
2640 for (j
= 0; j
< ways
; j
++) {
2641 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2647 if (ppcmas_tlb_check(env
, tlb
, &raddr
, address
, spid
)) {
2651 if (sas
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
2655 booke206_tlb_to_mas(env
, tlb
);
2660 /* no entry found, fill with defaults */
2661 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
2662 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
2663 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
2664 env
->spr
[SPR_BOOKE_MAS3
] = 0;
2665 env
->spr
[SPR_BOOKE_MAS7
] = 0;
2667 if (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
) {
2668 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
2671 env
->spr
[SPR_BOOKE_MAS1
] |= (env
->spr
[SPR_BOOKE_MAS6
] >> 16)
2674 /* next victim logic */
2675 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
2677 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
2678 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2681 static inline void booke206_invalidate_ea_tlb(CPUPPCState
*env
, int tlbn
,
2685 int ways
= booke206_tlb_ways(env
, tlbn
);
2688 for (i
= 0; i
< ways
; i
++) {
2689 ppcmas_tlb_t
*tlb
= booke206_get_tlbm(env
, tlbn
, ea
, i
);
2693 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2694 if (((tlb
->mas2
& MAS2_EPN_MASK
) == (ea
& mask
)) &&
2695 !(tlb
->mas1
& MAS1_IPROT
)) {
2696 tlb
->mas1
&= ~MAS1_VALID
;
2701 void helper_booke206_tlbivax(CPUPPCState
*env
, target_ulong address
)
2703 if (address
& 0x4) {
2704 /* flush all entries */
2705 if (address
& 0x8) {
2706 /* flush all of TLB1 */
2707 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB1
, 1);
2709 /* flush all of TLB0 */
2710 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB0
, 0);
2715 if (address
& 0x8) {
2716 /* flush TLB1 entries */
2717 booke206_invalidate_ea_tlb(env
, 1, address
);
2720 /* flush TLB0 entries */
2721 booke206_invalidate_ea_tlb(env
, 0, address
);
2722 tlb_flush_page(env
, address
& MAS2_EPN_MASK
);
2726 void helper_booke206_tlbilx0(CPUPPCState
*env
, target_ulong address
)
2728 /* XXX missing LPID handling */
2729 booke206_flush_tlb(env
, -1, 1);
2732 void helper_booke206_tlbilx1(CPUPPCState
*env
, target_ulong address
)
2735 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2736 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
2739 /* XXX missing LPID handling */
2740 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2741 tlb_size
= booke206_tlb_size(env
, i
);
2742 for (j
= 0; j
< tlb_size
; j
++) {
2743 if (!(tlb
[j
].mas1
& MAS1_IPROT
) &&
2744 ((tlb
[j
].mas1
& MAS1_TID_MASK
) == tid
)) {
2745 tlb
[j
].mas1
&= ~MAS1_VALID
;
2748 tlb
+= booke206_tlb_size(env
, i
);
2753 void helper_booke206_tlbilx3(CPUPPCState
*env
, target_ulong address
)
2757 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2758 int pid
= tid
>> MAS6_SPID_SHIFT
;
2759 int sgs
= env
->spr
[SPR_BOOKE_MAS5
] & MAS5_SGS
;
2760 int ind
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SIND
) ? MAS1_IND
: 0;
2761 /* XXX check for unsupported isize and raise an invalid opcode then */
2762 int size
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_ISIZE_MASK
;
2763 /* XXX implement MAV2 handling */
2766 /* XXX missing LPID handling */
2767 /* flush by pid and ea */
2768 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2769 int ways
= booke206_tlb_ways(env
, i
);
2771 for (j
= 0; j
< ways
; j
++) {
2772 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2776 if ((ppcmas_tlb_check(env
, tlb
, NULL
, address
, pid
) != 0) ||
2777 (tlb
->mas1
& MAS1_IPROT
) ||
2778 ((tlb
->mas1
& MAS1_IND
) != ind
) ||
2779 ((tlb
->mas8
& MAS8_TGS
) != sgs
)) {
2782 if (mav2
&& ((tlb
->mas1
& MAS1_TSIZE_MASK
) != size
)) {
2783 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2786 /* XXX e500mc doesn't match SAS, but other cores might */
2787 tlb
->mas1
&= ~MAS1_VALID
;
2793 void helper_booke206_tlbflush(CPUPPCState
*env
, uint32_t type
)
2798 flags
|= BOOKE206_FLUSH_TLB1
;
2802 flags
|= BOOKE206_FLUSH_TLB0
;
2805 booke206_flush_tlb(env
, flags
, 1);