2 * PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "sysemu/kvm.h"
23 #include "mmu-hash64.h"
24 #include "mmu-hash32.h"
28 //#define DEBUG_SOFTWARE_TLB
29 //#define DUMP_PAGE_TABLES
30 //#define DEBUG_SOFTWARE_TLB
31 //#define FLUSH_ALL_TLBS
34 # define LOG_MMU(...) qemu_log(__VA_ARGS__)
35 # define LOG_MMU_STATE(env) log_cpu_state((env), 0)
37 # define LOG_MMU(...) do { } while (0)
38 # define LOG_MMU_STATE(...) do { } while (0)
41 #ifdef DEBUG_SOFTWARE_TLB
42 # define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
44 # define LOG_SWTLB(...) do { } while (0)
48 # define LOG_BATS(...) qemu_log(__VA_ARGS__)
50 # define LOG_BATS(...) do { } while (0)
53 /*****************************************************************************/
54 /* PowerPC MMU emulation */
55 #if defined(CONFIG_USER_ONLY)
56 int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
, int rw
,
59 int exception
, error_code
;
62 exception
= POWERPC_EXCP_ISI
;
63 error_code
= 0x40000000;
65 exception
= POWERPC_EXCP_DSI
;
66 error_code
= 0x40000000;
68 error_code
|= 0x02000000;
70 env
->spr
[SPR_DAR
] = address
;
71 env
->spr
[SPR_DSISR
] = error_code
;
73 env
->exception_index
= exception
;
74 env
->error_code
= error_code
;
80 /* Common routines used by software and hardware TLBs emulation */
81 static inline int pte_is_valid(target_ulong pte0
)
83 return pte0
& 0x80000000 ? 1 : 0;
86 static inline void pte_invalidate(target_ulong
*pte0
)
91 #define PTE_PTEM_MASK 0x7FFFFFBF
92 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
94 static int pp_check(int key
, int pp
, int nx
)
98 /* Compute access rights */
105 access
|= PAGE_WRITE
;
121 access
= PAGE_READ
| PAGE_WRITE
;
132 static int check_prot(int prot
, int rw
, int access_type
)
136 if (access_type
== ACCESS_CODE
) {
137 if (prot
& PAGE_EXEC
) {
143 if (prot
& PAGE_WRITE
) {
149 if (prot
& PAGE_READ
) {
159 static inline int ppc6xx_tlb_pte_check(mmu_ctx_t
*ctx
, target_ulong pte0
,
160 target_ulong pte1
, int h
, int rw
, int type
)
162 target_ulong ptem
, mmask
;
163 int access
, ret
, pteh
, ptev
, pp
;
166 /* Check validity and table match */
167 ptev
= pte_is_valid(pte0
);
168 pteh
= (pte0
>> 6) & 1;
169 if (ptev
&& h
== pteh
) {
170 /* Check vsid & api */
171 ptem
= pte0
& PTE_PTEM_MASK
;
172 mmask
= PTE_CHECK_MASK
;
173 pp
= pte1
& 0x00000003;
174 if (ptem
== ctx
->ptem
) {
175 if (ctx
->raddr
!= (hwaddr
)-1ULL) {
176 /* all matches should have equal RPN, WIMG & PP */
177 if ((ctx
->raddr
& mmask
) != (pte1
& mmask
)) {
178 qemu_log("Bad RPN/WIMG/PP\n");
182 /* Compute access rights */
183 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
184 /* Keep the matching PTE informations */
187 ret
= check_prot(ctx
->prot
, rw
, type
);
190 LOG_MMU("PTE access granted !\n");
192 /* Access right violation */
193 LOG_MMU("PTE access rejected\n");
201 static int pte_update_flags(mmu_ctx_t
*ctx
, target_ulong
*pte1p
,
206 /* Update page flags */
207 if (!(*pte1p
& 0x00000100)) {
208 /* Update accessed flag */
209 *pte1p
|= 0x00000100;
212 if (!(*pte1p
& 0x00000080)) {
213 if (rw
== 1 && ret
== 0) {
214 /* Update changed flag */
215 *pte1p
|= 0x00000080;
218 /* Force page fault for first write access */
219 ctx
->prot
&= ~PAGE_WRITE
;
226 /* Software driven TLB helpers */
227 static inline int ppc6xx_tlb_getnum(CPUPPCState
*env
, target_ulong eaddr
,
228 int way
, int is_code
)
232 /* Select TLB num in a way from address */
233 nr
= (eaddr
>> TARGET_PAGE_BITS
) & (env
->tlb_per_way
- 1);
235 nr
+= env
->tlb_per_way
* way
;
236 /* 6xx have separate TLBs for instructions and data */
237 if (is_code
&& env
->id_tlbs
== 1) {
244 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState
*env
)
249 /* LOG_SWTLB("Invalidate all TLBs\n"); */
250 /* Invalidate all defined software TLB */
252 if (env
->id_tlbs
== 1) {
255 for (nr
= 0; nr
< max
; nr
++) {
256 tlb
= &env
->tlb
.tlb6
[nr
];
257 pte_invalidate(&tlb
->pte0
);
262 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState
*env
,
264 int is_code
, int match_epn
)
266 #if !defined(FLUSH_ALL_TLBS)
270 /* Invalidate ITLB + DTLB, all ways */
271 for (way
= 0; way
< env
->nb_ways
; way
++) {
272 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
, is_code
);
273 tlb
= &env
->tlb
.tlb6
[nr
];
274 if (pte_is_valid(tlb
->pte0
) && (match_epn
== 0 || eaddr
== tlb
->EPN
)) {
275 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx
"\n", nr
,
277 pte_invalidate(&tlb
->pte0
);
278 tlb_flush_page(env
, tlb
->EPN
);
282 /* XXX: PowerPC specification say this is valid as well */
283 ppc6xx_tlb_invalidate_all(env
);
287 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState
*env
,
288 target_ulong eaddr
, int is_code
)
290 ppc6xx_tlb_invalidate_virt2(env
, eaddr
, is_code
, 0);
293 static void ppc6xx_tlb_store(CPUPPCState
*env
, target_ulong EPN
, int way
,
294 int is_code
, target_ulong pte0
, target_ulong pte1
)
299 nr
= ppc6xx_tlb_getnum(env
, EPN
, way
, is_code
);
300 tlb
= &env
->tlb
.tlb6
[nr
];
301 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
302 " PTE1 " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
, EPN
, pte0
, pte1
);
303 /* Invalidate any pending reference in QEMU for this virtual address */
304 ppc6xx_tlb_invalidate_virt2(env
, EPN
, is_code
, 1);
308 /* Store last way for LRU mechanism */
312 static inline int ppc6xx_tlb_check(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
313 target_ulong eaddr
, int rw
, int access_type
)
320 ret
= -1; /* No TLB found */
321 for (way
= 0; way
< env
->nb_ways
; way
++) {
322 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
,
323 access_type
== ACCESS_CODE
? 1 : 0);
324 tlb
= &env
->tlb
.tlb6
[nr
];
325 /* This test "emulates" the PTE index match for hardware TLBs */
326 if ((eaddr
& TARGET_PAGE_MASK
) != tlb
->EPN
) {
327 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx
" " TARGET_FMT_lx
328 "] <> " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
,
329 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
330 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
, eaddr
);
333 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx
" <> " TARGET_FMT_lx
" "
334 TARGET_FMT_lx
" %c %c\n", nr
, env
->nb_tlb
,
335 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
336 tlb
->EPN
, eaddr
, tlb
->pte1
,
337 rw
? 'S' : 'L', access_type
== ACCESS_CODE
? 'I' : 'D');
338 switch (ppc6xx_tlb_pte_check(ctx
, tlb
->pte0
, tlb
->pte1
, 0, rw
, access_type
)) {
340 /* TLB inconsistency */
343 /* Access violation */
353 /* XXX: we should go on looping to check all TLBs consistency
354 * but we can speed-up the whole thing as the
355 * result would be undefined if TLBs are not consistent.
364 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx
" prot=%01x ret=%d\n",
365 ctx
->raddr
& TARGET_PAGE_MASK
, ctx
->prot
, ret
);
366 /* Update page flags */
367 pte_update_flags(ctx
, &env
->tlb
.tlb6
[best
].pte1
, ret
, rw
);
373 /* Perform BAT hit & translation */
374 static inline void bat_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
375 int *validp
, int *protp
, target_ulong
*BATu
,
381 bl
= (*BATu
& 0x00001FFC) << 15;
384 if (((msr_pr
== 0) && (*BATu
& 0x00000002)) ||
385 ((msr_pr
!= 0) && (*BATu
& 0x00000001))) {
387 pp
= *BATl
& 0x00000003;
389 prot
= PAGE_READ
| PAGE_EXEC
;
400 static int get_bat_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
401 target_ulong
virtual, int rw
, int type
)
403 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
404 target_ulong BEPIl
, BEPIu
, bl
;
408 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx
"\n", __func__
,
409 type
== ACCESS_CODE
? 'I' : 'D', virtual);
412 BATlt
= env
->IBAT
[1];
413 BATut
= env
->IBAT
[0];
416 BATlt
= env
->DBAT
[1];
417 BATut
= env
->DBAT
[0];
420 for (i
= 0; i
< env
->nb_BATs
; i
++) {
423 BEPIu
= *BATu
& 0xF0000000;
424 BEPIl
= *BATu
& 0x0FFE0000;
425 bat_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
426 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
427 " BATl " TARGET_FMT_lx
"\n", __func__
,
428 type
== ACCESS_CODE
? 'I' : 'D', i
, virtual, *BATu
, *BATl
);
429 if ((virtual & 0xF0000000) == BEPIu
&&
430 ((virtual & 0x0FFE0000) & ~bl
) == BEPIl
) {
433 /* Get physical address */
434 ctx
->raddr
= (*BATl
& 0xF0000000) |
435 ((virtual & 0x0FFE0000 & bl
) | (*BATl
& 0x0FFE0000)) |
436 (virtual & 0x0001F000);
437 /* Compute access rights */
439 ret
= check_prot(ctx
->prot
, rw
, type
);
441 LOG_BATS("BAT %d match: r " TARGET_FMT_plx
" prot=%c%c\n",
442 i
, ctx
->raddr
, ctx
->prot
& PAGE_READ
? 'R' : '-',
443 ctx
->prot
& PAGE_WRITE
? 'W' : '-');
450 #if defined(DEBUG_BATS)
451 if (qemu_log_enabled()) {
452 LOG_BATS("no BAT match for " TARGET_FMT_lx
":\n", virtual);
453 for (i
= 0; i
< 4; i
++) {
456 BEPIu
= *BATu
& 0xF0000000;
457 BEPIl
= *BATu
& 0x0FFE0000;
458 bl
= (*BATu
& 0x00001FFC) << 15;
459 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
460 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
461 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
462 __func__
, type
== ACCESS_CODE
? 'I' : 'D', i
, virtual,
463 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
472 /* Perform segment based translation */
473 static inline int get_segment_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
474 target_ulong eaddr
, int rw
, int type
)
478 int ds
, pr
, target_page_bits
;
480 target_ulong sr
, pgidx
;
485 sr
= env
->sr
[eaddr
>> 28];
486 ctx
->key
= (((sr
& 0x20000000) && (pr
!= 0)) ||
487 ((sr
& 0x40000000) && (pr
== 0))) ? 1 : 0;
488 ds
= sr
& 0x80000000 ? 1 : 0;
489 ctx
->nx
= sr
& 0x10000000 ? 1 : 0;
490 vsid
= sr
& 0x00FFFFFF;
491 target_page_bits
= TARGET_PAGE_BITS
;
492 LOG_MMU("Check segment v=" TARGET_FMT_lx
" %d " TARGET_FMT_lx
" nip="
493 TARGET_FMT_lx
" lr=" TARGET_FMT_lx
494 " ir=%d dr=%d pr=%d %d t=%d\n",
495 eaddr
, (int)(eaddr
>> 28), sr
, env
->nip
, env
->lr
, (int)msr_ir
,
496 (int)msr_dr
, pr
!= 0 ? 1 : 0, rw
, type
);
497 pgidx
= (eaddr
& ~SEGMENT_MASK_256M
) >> target_page_bits
;
499 ctx
->ptem
= (vsid
<< 7) | (pgidx
>> 10);
501 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx
"\n",
502 ctx
->key
, ds
, ctx
->nx
, vsid
);
505 /* Check if instruction fetch is allowed, if needed */
506 if (type
!= ACCESS_CODE
|| ctx
->nx
== 0) {
507 /* Page address translation */
508 LOG_MMU("htab_base " TARGET_FMT_plx
" htab_mask " TARGET_FMT_plx
509 " hash " TARGET_FMT_plx
"\n",
510 env
->htab_base
, env
->htab_mask
, hash
);
512 ctx
->hash
[1] = ~hash
;
514 /* Initialize real address with an invalid value */
515 ctx
->raddr
= (hwaddr
)-1ULL;
516 /* Software TLB search */
517 ret
= ppc6xx_tlb_check(env
, ctx
, eaddr
, rw
, type
);
518 #if defined(DUMP_PAGE_TABLES)
519 if (qemu_log_enabled()) {
521 uint32_t a0
, a1
, a2
, a3
;
523 qemu_log("Page table: " TARGET_FMT_plx
" len " TARGET_FMT_plx
524 "\n", sdr
, mask
+ 0x80);
525 for (curaddr
= sdr
; curaddr
< (sdr
+ mask
+ 0x80);
527 a0
= ldl_phys(curaddr
);
528 a1
= ldl_phys(curaddr
+ 4);
529 a2
= ldl_phys(curaddr
+ 8);
530 a3
= ldl_phys(curaddr
+ 12);
531 if (a0
!= 0 || a1
!= 0 || a2
!= 0 || a3
!= 0) {
532 qemu_log(TARGET_FMT_plx
": %08x %08x %08x %08x\n",
533 curaddr
, a0
, a1
, a2
, a3
);
539 LOG_MMU("No access allowed\n");
545 LOG_MMU("direct store...\n");
546 /* Direct-store segment : absolutely *BUGGY* for now */
548 /* Direct-store implies a 32-bit MMU.
549 * Check the Segment Register's bus unit ID (BUID).
551 sr
= env
->sr
[eaddr
>> 28];
552 if ((sr
& 0x1FF00000) >> 20 == 0x07f) {
553 /* Memory-forced I/O controller interface access */
554 /* If T=1 and BUID=x'07F', the 601 performs a memory access
555 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
557 ctx
->raddr
= ((sr
& 0xF) << 28) | (eaddr
& 0x0FFFFFFF);
558 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
564 /* Integer load/store : only access allowed */
567 /* No code fetch is allowed in direct-store areas */
570 /* Floating point load/store */
573 /* lwarx, ldarx or srwcx. */
576 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
577 /* Should make the instruction do no-op.
578 * As it already do no-op, it's quite easy :-)
586 qemu_log("ERROR: instruction should not need "
587 "address translation\n");
590 if ((rw
== 1 || ctx
->key
!= 1) && (rw
== 0 || ctx
->key
!= 0)) {
601 /* Generic TLB check function for embedded PowerPC implementations */
602 static int ppcemb_tlb_check(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
604 target_ulong address
, uint32_t pid
, int ext
,
609 /* Check valid flag */
610 if (!(tlb
->prot
& PAGE_VALID
)) {
613 mask
= ~(tlb
->size
- 1);
614 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx
" PID %u <=> " TARGET_FMT_lx
615 " " TARGET_FMT_lx
" %u %x\n", __func__
, i
, address
, pid
, tlb
->EPN
,
616 mask
, (uint32_t)tlb
->PID
, tlb
->prot
);
618 if (tlb
->PID
!= 0 && tlb
->PID
!= pid
) {
621 /* Check effective address */
622 if ((address
& mask
) != tlb
->EPN
) {
625 *raddrp
= (tlb
->RPN
& mask
) | (address
& ~mask
);
627 /* Extend the physical address to 36 bits */
628 *raddrp
|= (uint64_t)(tlb
->RPN
& 0xF) << 32;
634 /* Generic TLB search function for PowerPC embedded implementations */
635 static int ppcemb_tlb_search(CPUPPCState
*env
, target_ulong address
,
642 /* Default return value is no match */
644 for (i
= 0; i
< env
->nb_tlb
; i
++) {
645 tlb
= &env
->tlb
.tlbe
[i
];
646 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
, pid
, 0, i
) == 0) {
655 /* Helpers specific to PowerPC 40x implementations */
656 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState
*env
)
661 for (i
= 0; i
< env
->nb_tlb
; i
++) {
662 tlb
= &env
->tlb
.tlbe
[i
];
663 tlb
->prot
&= ~PAGE_VALID
;
668 static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState
*env
,
669 target_ulong eaddr
, uint32_t pid
)
671 #if !defined(FLUSH_ALL_TLBS)
674 target_ulong page
, end
;
677 for (i
= 0; i
< env
->nb_tlb
; i
++) {
678 tlb
= &env
->tlb
.tlbe
[i
];
679 if (ppcemb_tlb_check(env
, tlb
, &raddr
, eaddr
, pid
, 0, i
) == 0) {
680 end
= tlb
->EPN
+ tlb
->size
;
681 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
682 tlb_flush_page(env
, page
);
684 tlb
->prot
&= ~PAGE_VALID
;
689 ppc4xx_tlb_invalidate_all(env
);
693 static int mmu40x_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
694 target_ulong address
, int rw
,
699 int i
, ret
, zsel
, zpr
, pr
;
702 raddr
= (hwaddr
)-1ULL;
704 for (i
= 0; i
< env
->nb_tlb
; i
++) {
705 tlb
= &env
->tlb
.tlbe
[i
];
706 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
707 env
->spr
[SPR_40x_PID
], 0, i
) < 0) {
710 zsel
= (tlb
->attr
>> 4) & 0xF;
711 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (30 - (2 * zsel
))) & 0x3;
712 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
713 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
714 /* Check execute enable bit */
722 /* All accesses granted */
723 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
728 /* Raise Zone protection fault. */
729 env
->spr
[SPR_40x_ESR
] = 1 << 22;
737 /* Check from TLB entry */
738 ctx
->prot
= tlb
->prot
;
739 ret
= check_prot(ctx
->prot
, rw
, access_type
);
741 env
->spr
[SPR_40x_ESR
] = 0;
747 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
748 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
753 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
754 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
759 void store_40x_sler(CPUPPCState
*env
, uint32_t val
)
761 /* XXX: TO BE FIXED */
762 if (val
!= 0x00000000) {
763 cpu_abort(env
, "Little-endian regions are not supported by now\n");
765 env
->spr
[SPR_405_SLER
] = val
;
768 static inline int mmubooke_check_tlb(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
769 hwaddr
*raddr
, int *prot
,
770 target_ulong address
, int rw
,
771 int access_type
, int i
)
775 if (ppcemb_tlb_check(env
, tlb
, raddr
, address
,
776 env
->spr
[SPR_BOOKE_PID
],
777 !env
->nb_pids
, i
) >= 0) {
781 if (env
->spr
[SPR_BOOKE_PID1
] &&
782 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
783 env
->spr
[SPR_BOOKE_PID1
], 0, i
) >= 0) {
787 if (env
->spr
[SPR_BOOKE_PID2
] &&
788 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
789 env
->spr
[SPR_BOOKE_PID2
], 0, i
) >= 0) {
793 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
799 prot2
= tlb
->prot
& 0xF;
801 prot2
= (tlb
->prot
>> 4) & 0xF;
804 /* Check the address space */
805 if (access_type
== ACCESS_CODE
) {
806 if (msr_ir
!= (tlb
->attr
& 1)) {
807 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
812 if (prot2
& PAGE_EXEC
) {
813 LOG_SWTLB("%s: good TLB!\n", __func__
);
817 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
820 if (msr_dr
!= (tlb
->attr
& 1)) {
821 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
826 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
827 LOG_SWTLB("%s: found TLB!\n", __func__
);
831 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
838 static int mmubooke_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
839 target_ulong address
, int rw
,
847 raddr
= (hwaddr
)-1ULL;
848 for (i
= 0; i
< env
->nb_tlb
; i
++) {
849 tlb
= &env
->tlb
.tlbe
[i
];
850 ret
= mmubooke_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
, rw
,
859 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
860 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
863 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
864 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
870 static void booke206_flush_tlb(CPUPPCState
*env
, int flags
,
871 const int check_iprot
)
875 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
877 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
878 if (flags
& (1 << i
)) {
879 tlb_size
= booke206_tlb_size(env
, i
);
880 for (j
= 0; j
< tlb_size
; j
++) {
881 if (!check_iprot
|| !(tlb
[j
].mas1
& MAS1_IPROT
)) {
882 tlb
[j
].mas1
&= ~MAS1_VALID
;
886 tlb
+= booke206_tlb_size(env
, i
);
892 static hwaddr
booke206_tlb_to_page_size(CPUPPCState
*env
,
897 tlbm_size
= (tlb
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
899 return 1024ULL << tlbm_size
;
902 /* TLB check function for MAS based SoftTLBs */
903 static int ppcmas_tlb_check(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
905 target_ulong address
, uint32_t pid
)
910 /* Check valid flag */
911 if (!(tlb
->mas1
& MAS1_VALID
)) {
915 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
916 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx
" PID=0x%x MAS1=0x%x MAS2=0x%"
917 PRIx64
" mask=0x" TARGET_FMT_lx
" MAS7_3=0x%" PRIx64
" MAS8=%x\n",
918 __func__
, address
, pid
, tlb
->mas1
, tlb
->mas2
, mask
, tlb
->mas7_3
,
922 tlb_pid
= (tlb
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
;
923 if (tlb_pid
!= 0 && tlb_pid
!= pid
) {
927 /* Check effective address */
928 if ((address
& mask
) != (tlb
->mas2
& MAS2_EPN_MASK
)) {
933 *raddrp
= (tlb
->mas7_3
& mask
) | (address
& ~mask
);
939 static int mmubooke206_check_tlb(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
940 hwaddr
*raddr
, int *prot
,
941 target_ulong address
, int rw
,
947 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
,
948 env
->spr
[SPR_BOOKE_PID
]) >= 0) {
952 if (env
->spr
[SPR_BOOKE_PID1
] &&
953 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
954 env
->spr
[SPR_BOOKE_PID1
]) >= 0) {
958 if (env
->spr
[SPR_BOOKE_PID2
] &&
959 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
960 env
->spr
[SPR_BOOKE_PID2
]) >= 0) {
964 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
970 if (tlb
->mas7_3
& MAS3_UR
) {
973 if (tlb
->mas7_3
& MAS3_UW
) {
976 if (tlb
->mas7_3
& MAS3_UX
) {
980 if (tlb
->mas7_3
& MAS3_SR
) {
983 if (tlb
->mas7_3
& MAS3_SW
) {
986 if (tlb
->mas7_3
& MAS3_SX
) {
991 /* Check the address space and permissions */
992 if (access_type
== ACCESS_CODE
) {
993 if (msr_ir
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
994 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
999 if (prot2
& PAGE_EXEC
) {
1000 LOG_SWTLB("%s: good TLB!\n", __func__
);
1004 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
1007 if (msr_dr
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1008 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1013 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
1014 LOG_SWTLB("%s: found TLB!\n", __func__
);
1018 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
1025 static int mmubooke206_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1026 target_ulong address
, int rw
,
1034 raddr
= (hwaddr
)-1ULL;
1036 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1037 int ways
= booke206_tlb_ways(env
, i
);
1039 for (j
= 0; j
< ways
; j
++) {
1040 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
1044 ret
= mmubooke206_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
,
1056 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
1057 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1060 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
1061 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
1067 static const char *book3e_tsize_to_str
[32] = {
1068 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1069 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1070 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1074 static void mmubooke_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1077 ppcemb_tlb_t
*entry
;
1080 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1081 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1085 cpu_fprintf(f
, "\nTLB:\n");
1086 cpu_fprintf(f
, "Effective Physical Size PID Prot "
1089 entry
= &env
->tlb
.tlbe
[0];
1090 for (i
= 0; i
< env
->nb_tlb
; i
++, entry
++) {
1093 uint64_t size
= (uint64_t)entry
->size
;
1096 /* Check valid flag */
1097 if (!(entry
->prot
& PAGE_VALID
)) {
1101 mask
= ~(entry
->size
- 1);
1102 ea
= entry
->EPN
& mask
;
1103 pa
= entry
->RPN
& mask
;
1104 /* Extend the physical address to 36 bits */
1105 pa
|= (hwaddr
)(entry
->RPN
& 0xF) << 32;
1108 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"M", size
/ 1024);
1110 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"k", size
);
1112 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %s %-5u %08x %08x\n",
1113 (uint64_t)ea
, (uint64_t)pa
, size_buf
, (uint32_t)entry
->PID
,
1114 entry
->prot
, entry
->attr
);
1119 static void mmubooke206_dump_one_tlb(FILE *f
, fprintf_function cpu_fprintf
,
1120 CPUPPCState
*env
, int tlbn
, int offset
,
1123 ppcmas_tlb_t
*entry
;
1126 cpu_fprintf(f
, "\nTLB%d:\n", tlbn
);
1127 cpu_fprintf(f
, "Effective Physical Size TID TS SRWX"
1128 " URWX WIMGE U0123\n");
1130 entry
= &env
->tlb
.tlbm
[offset
];
1131 for (i
= 0; i
< tlbsize
; i
++, entry
++) {
1132 hwaddr ea
, pa
, size
;
1135 if (!(entry
->mas1
& MAS1_VALID
)) {
1139 tsize
= (entry
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1140 size
= 1024ULL << tsize
;
1141 ea
= entry
->mas2
& ~(size
- 1);
1142 pa
= entry
->mas7_3
& ~(size
- 1);
1144 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %4s %-5u %1u S%c%c%c"
1145 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1146 (uint64_t)ea
, (uint64_t)pa
,
1147 book3e_tsize_to_str
[tsize
],
1148 (entry
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
,
1149 (entry
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
,
1150 entry
->mas7_3
& MAS3_SR
? 'R' : '-',
1151 entry
->mas7_3
& MAS3_SW
? 'W' : '-',
1152 entry
->mas7_3
& MAS3_SX
? 'X' : '-',
1153 entry
->mas7_3
& MAS3_UR
? 'R' : '-',
1154 entry
->mas7_3
& MAS3_UW
? 'W' : '-',
1155 entry
->mas7_3
& MAS3_UX
? 'X' : '-',
1156 entry
->mas2
& MAS2_W
? 'W' : '-',
1157 entry
->mas2
& MAS2_I
? 'I' : '-',
1158 entry
->mas2
& MAS2_M
? 'M' : '-',
1159 entry
->mas2
& MAS2_G
? 'G' : '-',
1160 entry
->mas2
& MAS2_E
? 'E' : '-',
1161 entry
->mas7_3
& MAS3_U0
? '0' : '-',
1162 entry
->mas7_3
& MAS3_U1
? '1' : '-',
1163 entry
->mas7_3
& MAS3_U2
? '2' : '-',
1164 entry
->mas7_3
& MAS3_U3
? '3' : '-');
1168 static void mmubooke206_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1174 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1175 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1179 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1180 int size
= booke206_tlb_size(env
, i
);
1186 mmubooke206_dump_one_tlb(f
, cpu_fprintf
, env
, i
, offset
, size
);
1191 void dump_mmu(FILE *f
, fprintf_function cpu_fprintf
, CPUPPCState
*env
)
1193 switch (env
->mmu_model
) {
1194 case POWERPC_MMU_BOOKE
:
1195 mmubooke_dump_mmu(f
, cpu_fprintf
, env
);
1197 case POWERPC_MMU_BOOKE206
:
1198 mmubooke206_dump_mmu(f
, cpu_fprintf
, env
);
1200 #if defined(TARGET_PPC64)
1201 case POWERPC_MMU_64B
:
1202 case POWERPC_MMU_2_06
:
1203 case POWERPC_MMU_2_06d
:
1204 dump_slb(f
, cpu_fprintf
, env
);
1208 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented\n", __func__
);
1212 static inline int check_physical(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1213 target_ulong eaddr
, int rw
)
1218 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1220 switch (env
->mmu_model
) {
1221 case POWERPC_MMU_SOFT_6xx
:
1222 case POWERPC_MMU_SOFT_74xx
:
1223 case POWERPC_MMU_SOFT_4xx
:
1224 case POWERPC_MMU_REAL
:
1225 case POWERPC_MMU_BOOKE
:
1226 ctx
->prot
|= PAGE_WRITE
;
1229 case POWERPC_MMU_SOFT_4xx_Z
:
1230 if (unlikely(msr_pe
!= 0)) {
1231 /* 403 family add some particular protections,
1232 * using PBL/PBU registers for accesses with no translation.
1235 /* Check PLB validity */
1236 (env
->pb
[0] < env
->pb
[1] &&
1237 /* and address in plb area */
1238 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1239 (env
->pb
[2] < env
->pb
[3] &&
1240 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1241 if (in_plb
^ msr_px
) {
1242 /* Access in protected area */
1244 /* Access is not allowed */
1248 /* Read-write access is allowed */
1249 ctx
->prot
|= PAGE_WRITE
;
1255 /* Caller's checks mean we should never get here for other models */
1263 static int get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1264 target_ulong eaddr
, int rw
, int access_type
)
1267 bool real_mode
= (access_type
== ACCESS_CODE
&& msr_ir
== 0)
1268 || (access_type
!= ACCESS_CODE
&& msr_dr
== 0);
1271 qemu_log("%s\n", __func__
);
1274 switch (env
->mmu_model
) {
1275 case POWERPC_MMU_SOFT_6xx
:
1276 case POWERPC_MMU_SOFT_74xx
:
1278 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1280 /* Try to find a BAT */
1281 if (env
->nb_BATs
!= 0) {
1282 ret
= get_bat_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1285 /* We didn't match any BAT entry or don't have BATs */
1286 ret
= get_segment_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1291 case POWERPC_MMU_SOFT_4xx
:
1292 case POWERPC_MMU_SOFT_4xx_Z
:
1294 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1296 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1300 case POWERPC_MMU_BOOKE
:
1301 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1304 case POWERPC_MMU_BOOKE206
:
1305 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1308 case POWERPC_MMU_MPC8xx
:
1310 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1312 case POWERPC_MMU_REAL
:
1314 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1316 cpu_abort(env
, "PowerPC in real mode do not do any translation\n");
1320 cpu_abort(env
, "Unknown or invalid MMU model\n");
1324 qemu_log("%s address " TARGET_FMT_lx
" => %d " TARGET_FMT_plx
"\n",
1325 __func__
, eaddr
, ret
, ctx
->raddr
);
1331 hwaddr
cpu_get_phys_page_debug(CPUPPCState
*env
, target_ulong addr
)
1335 switch (env
->mmu_model
) {
1336 #if defined(TARGET_PPC64)
1337 case POWERPC_MMU_64B
:
1338 case POWERPC_MMU_2_06
:
1339 case POWERPC_MMU_2_06d
:
1340 return ppc_hash64_get_phys_page_debug(env
, addr
);
1343 case POWERPC_MMU_32B
:
1344 case POWERPC_MMU_601
:
1345 return ppc_hash32_get_phys_page_debug(env
, addr
);
1351 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0)) {
1355 return ctx
.raddr
& TARGET_PAGE_MASK
;
1358 static void booke206_update_mas_tlb_miss(CPUPPCState
*env
, target_ulong address
,
1361 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
1362 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
1363 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
1364 env
->spr
[SPR_BOOKE_MAS3
] = 0;
1365 env
->spr
[SPR_BOOKE_MAS6
] = 0;
1366 env
->spr
[SPR_BOOKE_MAS7
] = 0;
1369 if (((rw
== 2) && msr_ir
) || ((rw
!= 2) && msr_dr
)) {
1370 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
1371 env
->spr
[SPR_BOOKE_MAS6
] |= MAS6_SAS
;
1374 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_VALID
;
1375 env
->spr
[SPR_BOOKE_MAS2
] |= address
& MAS2_EPN_MASK
;
1377 switch (env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TIDSELD_PIDZ
) {
1378 case MAS4_TIDSELD_PID0
:
1379 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID
] << MAS1_TID_SHIFT
;
1381 case MAS4_TIDSELD_PID1
:
1382 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID1
] << MAS1_TID_SHIFT
;
1384 case MAS4_TIDSELD_PID2
:
1385 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID2
] << MAS1_TID_SHIFT
;
1389 env
->spr
[SPR_BOOKE_MAS6
] |= env
->spr
[SPR_BOOKE_PID
] << 16;
1391 /* next victim logic */
1392 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
1394 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
1395 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
1398 /* Perform address translation */
1399 int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
, int rw
,
1406 switch (env
->mmu_model
) {
1407 #if defined(TARGET_PPC64)
1408 case POWERPC_MMU_64B
:
1409 case POWERPC_MMU_2_06
:
1410 case POWERPC_MMU_2_06d
:
1411 return ppc_hash64_handle_mmu_fault(env
, address
, rw
, mmu_idx
);
1414 case POWERPC_MMU_32B
:
1415 case POWERPC_MMU_601
:
1416 return ppc_hash32_handle_mmu_fault(env
, address
, rw
, mmu_idx
);
1419 ; /* Otherwise fall through to the general code below */
1425 access_type
= ACCESS_CODE
;
1428 access_type
= env
->access_type
;
1430 ret
= get_physical_address(env
, &ctx
, address
, rw
, access_type
);
1432 tlb_set_page(env
, address
& TARGET_PAGE_MASK
,
1433 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1434 mmu_idx
, TARGET_PAGE_SIZE
);
1436 } else if (ret
< 0) {
1438 if (access_type
== ACCESS_CODE
) {
1441 /* No matches in page tables or TLB */
1442 switch (env
->mmu_model
) {
1443 case POWERPC_MMU_SOFT_6xx
:
1444 env
->exception_index
= POWERPC_EXCP_IFTLB
;
1445 env
->error_code
= 1 << 18;
1446 env
->spr
[SPR_IMISS
] = address
;
1447 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1449 case POWERPC_MMU_SOFT_74xx
:
1450 env
->exception_index
= POWERPC_EXCP_IFTLB
;
1452 case POWERPC_MMU_SOFT_4xx
:
1453 case POWERPC_MMU_SOFT_4xx_Z
:
1454 env
->exception_index
= POWERPC_EXCP_ITLB
;
1455 env
->error_code
= 0;
1456 env
->spr
[SPR_40x_DEAR
] = address
;
1457 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1459 case POWERPC_MMU_BOOKE206
:
1460 booke206_update_mas_tlb_miss(env
, address
, rw
);
1462 case POWERPC_MMU_BOOKE
:
1463 env
->exception_index
= POWERPC_EXCP_ITLB
;
1464 env
->error_code
= 0;
1465 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1467 case POWERPC_MMU_MPC8xx
:
1469 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1471 case POWERPC_MMU_REAL
:
1472 cpu_abort(env
, "PowerPC in real mode should never raise "
1473 "any MMU exceptions\n");
1476 cpu_abort(env
, "Unknown or invalid MMU model\n");
1481 /* Access rights violation */
1482 env
->exception_index
= POWERPC_EXCP_ISI
;
1483 env
->error_code
= 0x08000000;
1486 /* No execute protection violation */
1487 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1488 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1489 env
->spr
[SPR_BOOKE_ESR
] = 0x00000000;
1491 env
->exception_index
= POWERPC_EXCP_ISI
;
1492 env
->error_code
= 0x10000000;
1495 /* Direct store exception */
1496 /* No code fetch is allowed in direct-store areas */
1497 env
->exception_index
= POWERPC_EXCP_ISI
;
1498 env
->error_code
= 0x10000000;
1504 /* No matches in page tables or TLB */
1505 switch (env
->mmu_model
) {
1506 case POWERPC_MMU_SOFT_6xx
:
1508 env
->exception_index
= POWERPC_EXCP_DSTLB
;
1509 env
->error_code
= 1 << 16;
1511 env
->exception_index
= POWERPC_EXCP_DLTLB
;
1512 env
->error_code
= 0;
1514 env
->spr
[SPR_DMISS
] = address
;
1515 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1517 env
->error_code
|= ctx
.key
<< 19;
1518 env
->spr
[SPR_HASH1
] = env
->htab_base
+
1519 get_pteg_offset32(env
, ctx
.hash
[0]);
1520 env
->spr
[SPR_HASH2
] = env
->htab_base
+
1521 get_pteg_offset32(env
, ctx
.hash
[1]);
1523 case POWERPC_MMU_SOFT_74xx
:
1525 env
->exception_index
= POWERPC_EXCP_DSTLB
;
1527 env
->exception_index
= POWERPC_EXCP_DLTLB
;
1530 /* Implement LRU algorithm */
1531 env
->error_code
= ctx
.key
<< 19;
1532 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1533 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1534 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1536 case POWERPC_MMU_SOFT_4xx
:
1537 case POWERPC_MMU_SOFT_4xx_Z
:
1538 env
->exception_index
= POWERPC_EXCP_DTLB
;
1539 env
->error_code
= 0;
1540 env
->spr
[SPR_40x_DEAR
] = address
;
1542 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1544 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1547 case POWERPC_MMU_MPC8xx
:
1549 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1551 case POWERPC_MMU_BOOKE206
:
1552 booke206_update_mas_tlb_miss(env
, address
, rw
);
1554 case POWERPC_MMU_BOOKE
:
1555 env
->exception_index
= POWERPC_EXCP_DTLB
;
1556 env
->error_code
= 0;
1557 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1558 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1560 case POWERPC_MMU_REAL
:
1561 cpu_abort(env
, "PowerPC in real mode should never raise "
1562 "any MMU exceptions\n");
1565 cpu_abort(env
, "Unknown or invalid MMU model\n");
1570 /* Access rights violation */
1571 env
->exception_index
= POWERPC_EXCP_DSI
;
1572 env
->error_code
= 0;
1573 if (env
->mmu_model
== POWERPC_MMU_SOFT_4xx
1574 || env
->mmu_model
== POWERPC_MMU_SOFT_4xx_Z
) {
1575 env
->spr
[SPR_40x_DEAR
] = address
;
1577 env
->spr
[SPR_40x_ESR
] |= 0x00800000;
1579 } else if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1580 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1581 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1582 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1584 env
->spr
[SPR_DAR
] = address
;
1586 env
->spr
[SPR_DSISR
] = 0x0A000000;
1588 env
->spr
[SPR_DSISR
] = 0x08000000;
1593 /* Direct store exception */
1594 switch (access_type
) {
1596 /* Floating point load/store */
1597 env
->exception_index
= POWERPC_EXCP_ALIGN
;
1598 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1599 env
->spr
[SPR_DAR
] = address
;
1602 /* lwarx, ldarx or stwcx. */
1603 env
->exception_index
= POWERPC_EXCP_DSI
;
1604 env
->error_code
= 0;
1605 env
->spr
[SPR_DAR
] = address
;
1607 env
->spr
[SPR_DSISR
] = 0x06000000;
1609 env
->spr
[SPR_DSISR
] = 0x04000000;
1613 /* eciwx or ecowx */
1614 env
->exception_index
= POWERPC_EXCP_DSI
;
1615 env
->error_code
= 0;
1616 env
->spr
[SPR_DAR
] = address
;
1618 env
->spr
[SPR_DSISR
] = 0x06100000;
1620 env
->spr
[SPR_DSISR
] = 0x04100000;
1624 printf("DSI: invalid exception (%d)\n", ret
);
1625 env
->exception_index
= POWERPC_EXCP_PROGRAM
;
1627 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1628 env
->spr
[SPR_DAR
] = address
;
1635 printf("%s: set exception to %d %02x\n", __func__
,
1636 env
->exception
, env
->error_code
);
1644 /*****************************************************************************/
1645 /* BATs management */
1646 #if !defined(FLUSH_ALL_TLBS)
1647 static inline void do_invalidate_BAT(CPUPPCState
*env
, target_ulong BATu
,
1650 target_ulong base
, end
, page
;
1652 base
= BATu
& ~0x0001FFFF;
1653 end
= base
+ mask
+ 0x00020000;
1654 LOG_BATS("Flush BAT from " TARGET_FMT_lx
" to " TARGET_FMT_lx
" ("
1655 TARGET_FMT_lx
")\n", base
, end
, mask
);
1656 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
1657 tlb_flush_page(env
, page
);
1659 LOG_BATS("Flush done\n");
1663 static inline void dump_store_bat(CPUPPCState
*env
, char ID
, int ul
, int nr
,
1666 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx
" (" TARGET_FMT_lx
")\n", ID
,
1667 nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1670 void helper_store_ibatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1674 dump_store_bat(env
, 'I', 0, nr
, value
);
1675 if (env
->IBAT
[0][nr
] != value
) {
1676 mask
= (value
<< 15) & 0x0FFE0000UL
;
1677 #if !defined(FLUSH_ALL_TLBS)
1678 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1680 /* When storing valid upper BAT, mask BEPI and BRPN
1681 * and invalidate all TLBs covered by this BAT
1683 mask
= (value
<< 15) & 0x0FFE0000UL
;
1684 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1685 (value
& ~0x0001FFFFUL
& ~mask
);
1686 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1687 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1688 #if !defined(FLUSH_ALL_TLBS)
1689 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1696 void helper_store_ibatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1698 dump_store_bat(env
, 'I', 1, nr
, value
);
1699 env
->IBAT
[1][nr
] = value
;
1702 void helper_store_dbatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1706 dump_store_bat(env
, 'D', 0, nr
, value
);
1707 if (env
->DBAT
[0][nr
] != value
) {
1708 /* When storing valid upper BAT, mask BEPI and BRPN
1709 * and invalidate all TLBs covered by this BAT
1711 mask
= (value
<< 15) & 0x0FFE0000UL
;
1712 #if !defined(FLUSH_ALL_TLBS)
1713 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1715 mask
= (value
<< 15) & 0x0FFE0000UL
;
1716 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1717 (value
& ~0x0001FFFFUL
& ~mask
);
1718 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1719 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1720 #if !defined(FLUSH_ALL_TLBS)
1721 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1728 void helper_store_dbatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1730 dump_store_bat(env
, 'D', 1, nr
, value
);
1731 env
->DBAT
[1][nr
] = value
;
1734 void helper_store_601_batu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1737 #if defined(FLUSH_ALL_TLBS)
1741 dump_store_bat(env
, 'I', 0, nr
, value
);
1742 if (env
->IBAT
[0][nr
] != value
) {
1743 #if defined(FLUSH_ALL_TLBS)
1746 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1747 if (env
->IBAT
[1][nr
] & 0x40) {
1748 /* Invalidate BAT only if it is valid */
1749 #if !defined(FLUSH_ALL_TLBS)
1750 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1755 /* When storing valid upper BAT, mask BEPI and BRPN
1756 * and invalidate all TLBs covered by this BAT
1758 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1759 (value
& ~0x0001FFFFUL
& ~mask
);
1760 env
->DBAT
[0][nr
] = env
->IBAT
[0][nr
];
1761 if (env
->IBAT
[1][nr
] & 0x40) {
1762 #if !defined(FLUSH_ALL_TLBS)
1763 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1768 #if defined(FLUSH_ALL_TLBS)
1776 void helper_store_601_batl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1778 #if !defined(FLUSH_ALL_TLBS)
1784 dump_store_bat(env
, 'I', 1, nr
, value
);
1785 if (env
->IBAT
[1][nr
] != value
) {
1786 #if defined(FLUSH_ALL_TLBS)
1789 if (env
->IBAT
[1][nr
] & 0x40) {
1790 #if !defined(FLUSH_ALL_TLBS)
1791 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1792 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1798 #if !defined(FLUSH_ALL_TLBS)
1799 mask
= (value
<< 17) & 0x0FFE0000UL
;
1800 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1805 env
->IBAT
[1][nr
] = value
;
1806 env
->DBAT
[1][nr
] = value
;
1807 #if defined(FLUSH_ALL_TLBS)
1815 /*****************************************************************************/
1816 /* TLB management */
1817 void ppc_tlb_invalidate_all(CPUPPCState
*env
)
1819 switch (env
->mmu_model
) {
1820 case POWERPC_MMU_SOFT_6xx
:
1821 case POWERPC_MMU_SOFT_74xx
:
1822 ppc6xx_tlb_invalidate_all(env
);
1824 case POWERPC_MMU_SOFT_4xx
:
1825 case POWERPC_MMU_SOFT_4xx_Z
:
1826 ppc4xx_tlb_invalidate_all(env
);
1828 case POWERPC_MMU_REAL
:
1829 cpu_abort(env
, "No TLB for PowerPC 4xx in real mode\n");
1831 case POWERPC_MMU_MPC8xx
:
1833 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1835 case POWERPC_MMU_BOOKE
:
1838 case POWERPC_MMU_BOOKE206
:
1839 booke206_flush_tlb(env
, -1, 0);
1841 case POWERPC_MMU_32B
:
1842 case POWERPC_MMU_601
:
1843 #if defined(TARGET_PPC64)
1844 case POWERPC_MMU_64B
:
1845 case POWERPC_MMU_2_06
:
1846 case POWERPC_MMU_2_06d
:
1847 #endif /* defined(TARGET_PPC64) */
1852 cpu_abort(env
, "Unknown MMU model\n");
1857 void ppc_tlb_invalidate_one(CPUPPCState
*env
, target_ulong addr
)
1859 #if !defined(FLUSH_ALL_TLBS)
1860 addr
&= TARGET_PAGE_MASK
;
1861 switch (env
->mmu_model
) {
1862 case POWERPC_MMU_SOFT_6xx
:
1863 case POWERPC_MMU_SOFT_74xx
:
1864 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
1865 if (env
->id_tlbs
== 1) {
1866 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
1869 case POWERPC_MMU_SOFT_4xx
:
1870 case POWERPC_MMU_SOFT_4xx_Z
:
1871 ppc4xx_tlb_invalidate_virt(env
, addr
, env
->spr
[SPR_40x_PID
]);
1873 case POWERPC_MMU_REAL
:
1874 cpu_abort(env
, "No TLB for PowerPC 4xx in real mode\n");
1876 case POWERPC_MMU_MPC8xx
:
1878 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1880 case POWERPC_MMU_BOOKE
:
1882 cpu_abort(env
, "BookE MMU model is not implemented\n");
1884 case POWERPC_MMU_BOOKE206
:
1886 cpu_abort(env
, "BookE 2.06 MMU model is not implemented\n");
1888 case POWERPC_MMU_32B
:
1889 case POWERPC_MMU_601
:
1890 /* tlbie invalidate TLBs for all segments */
1891 addr
&= ~((target_ulong
)-1ULL << 28);
1892 /* XXX: this case should be optimized,
1893 * giving a mask to tlb_flush_page
1895 tlb_flush_page(env
, addr
| (0x0 << 28));
1896 tlb_flush_page(env
, addr
| (0x1 << 28));
1897 tlb_flush_page(env
, addr
| (0x2 << 28));
1898 tlb_flush_page(env
, addr
| (0x3 << 28));
1899 tlb_flush_page(env
, addr
| (0x4 << 28));
1900 tlb_flush_page(env
, addr
| (0x5 << 28));
1901 tlb_flush_page(env
, addr
| (0x6 << 28));
1902 tlb_flush_page(env
, addr
| (0x7 << 28));
1903 tlb_flush_page(env
, addr
| (0x8 << 28));
1904 tlb_flush_page(env
, addr
| (0x9 << 28));
1905 tlb_flush_page(env
, addr
| (0xA << 28));
1906 tlb_flush_page(env
, addr
| (0xB << 28));
1907 tlb_flush_page(env
, addr
| (0xC << 28));
1908 tlb_flush_page(env
, addr
| (0xD << 28));
1909 tlb_flush_page(env
, addr
| (0xE << 28));
1910 tlb_flush_page(env
, addr
| (0xF << 28));
1912 #if defined(TARGET_PPC64)
1913 case POWERPC_MMU_64B
:
1914 case POWERPC_MMU_2_06
:
1915 case POWERPC_MMU_2_06d
:
1916 /* tlbie invalidate TLBs for all segments */
1917 /* XXX: given the fact that there are too many segments to invalidate,
1918 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
1919 * we just invalidate all TLBs
1923 #endif /* defined(TARGET_PPC64) */
1926 cpu_abort(env
, "Unknown MMU model\n");
1930 ppc_tlb_invalidate_all(env
);
1934 /*****************************************************************************/
1935 /* Special registers manipulation */
1936 void ppc_store_sdr1(CPUPPCState
*env
, target_ulong value
)
1938 LOG_MMU("%s: " TARGET_FMT_lx
"\n", __func__
, value
);
1939 if (env
->spr
[SPR_SDR1
] != value
) {
1940 env
->spr
[SPR_SDR1
] = value
;
1941 #if defined(TARGET_PPC64)
1942 if (env
->mmu_model
& POWERPC_MMU_64
) {
1943 target_ulong htabsize
= value
& SDR_64_HTABSIZE
;
1945 if (htabsize
> 28) {
1946 fprintf(stderr
, "Invalid HTABSIZE 0x" TARGET_FMT_lx
1947 " stored in SDR1\n", htabsize
);
1950 env
->htab_mask
= (1ULL << (htabsize
+ 18)) - 1;
1951 env
->htab_base
= value
& SDR_64_HTABORG
;
1953 #endif /* defined(TARGET_PPC64) */
1955 /* FIXME: Should check for valid HTABMASK values */
1956 env
->htab_mask
= ((value
& SDR_32_HTABMASK
) << 16) | 0xFFFF;
1957 env
->htab_base
= value
& SDR_32_HTABORG
;
1963 /* Segment registers load and store */
1964 target_ulong
helper_load_sr(CPUPPCState
*env
, target_ulong sr_num
)
1966 #if defined(TARGET_PPC64)
1967 if (env
->mmu_model
& POWERPC_MMU_64
) {
1972 return env
->sr
[sr_num
];
1975 void helper_store_sr(CPUPPCState
*env
, target_ulong srnum
, target_ulong value
)
1977 LOG_MMU("%s: reg=%d " TARGET_FMT_lx
" " TARGET_FMT_lx
"\n", __func__
,
1978 (int)srnum
, value
, env
->sr
[srnum
]);
1979 #if defined(TARGET_PPC64)
1980 if (env
->mmu_model
& POWERPC_MMU_64
) {
1981 uint64_t rb
= 0, rs
= 0;
1984 rb
|= ((uint32_t)srnum
& 0xf) << 28;
1985 /* Set the valid bit */
1988 rb
|= (uint32_t)srnum
;
1991 rs
|= (value
& 0xfffffff) << 12;
1993 rs
|= ((value
>> 27) & 0xf) << 8;
1995 ppc_store_slb(env
, rb
, rs
);
1998 if (env
->sr
[srnum
] != value
) {
1999 env
->sr
[srnum
] = value
;
2000 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2001 flusing the whole TLB. */
2002 #if !defined(FLUSH_ALL_TLBS) && 0
2004 target_ulong page
, end
;
2005 /* Invalidate 256 MB of virtual memory */
2006 page
= (16 << 20) * srnum
;
2007 end
= page
+ (16 << 20);
2008 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
2009 tlb_flush_page(env
, page
);
2017 #endif /* !defined(CONFIG_USER_ONLY) */
2019 #if !defined(CONFIG_USER_ONLY)
2020 /* TLB management */
2021 void helper_tlbia(CPUPPCState
*env
)
2023 ppc_tlb_invalidate_all(env
);
2026 void helper_tlbie(CPUPPCState
*env
, target_ulong addr
)
2028 ppc_tlb_invalidate_one(env
, addr
);
2031 /* Software driven TLBs management */
2032 /* PowerPC 602/603 software TLB load instructions helpers */
2033 static void do_6xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2035 target_ulong RPN
, CMP
, EPN
;
2038 RPN
= env
->spr
[SPR_RPA
];
2040 CMP
= env
->spr
[SPR_ICMP
];
2041 EPN
= env
->spr
[SPR_IMISS
];
2043 CMP
= env
->spr
[SPR_DCMP
];
2044 EPN
= env
->spr
[SPR_DMISS
];
2046 way
= (env
->spr
[SPR_SRR1
] >> 17) & 1;
2047 (void)EPN
; /* avoid a compiler warning */
2048 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2049 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2051 /* Store this TLB */
2052 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2053 way
, is_code
, CMP
, RPN
);
2056 void helper_6xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2058 do_6xx_tlb(env
, EPN
, 0);
2061 void helper_6xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2063 do_6xx_tlb(env
, EPN
, 1);
2066 /* PowerPC 74xx software TLB load instructions helpers */
2067 static void do_74xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2069 target_ulong RPN
, CMP
, EPN
;
2072 RPN
= env
->spr
[SPR_PTELO
];
2073 CMP
= env
->spr
[SPR_PTEHI
];
2074 EPN
= env
->spr
[SPR_TLBMISS
] & ~0x3;
2075 way
= env
->spr
[SPR_TLBMISS
] & 0x3;
2076 (void)EPN
; /* avoid a compiler warning */
2077 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2078 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2080 /* Store this TLB */
2081 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2082 way
, is_code
, CMP
, RPN
);
2085 void helper_74xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2087 do_74xx_tlb(env
, EPN
, 0);
2090 void helper_74xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2092 do_74xx_tlb(env
, EPN
, 1);
2095 /*****************************************************************************/
2096 /* PowerPC 601 specific instructions (POWER bridge) */
2098 target_ulong
helper_rac(CPUPPCState
*env
, target_ulong addr
)
2102 target_ulong ret
= 0;
2104 /* We don't have to generate many instances of this instruction,
2105 * as rac is supervisor only.
2107 /* XXX: FIX THIS: Pretend we have no BAT */
2108 nb_BATs
= env
->nb_BATs
;
2110 if (get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) == 0) {
2113 env
->nb_BATs
= nb_BATs
;
2117 static inline target_ulong
booke_tlb_to_page_size(int size
)
2119 return 1024 << (2 * size
);
2122 static inline int booke_page_size_to_tlb(target_ulong page_size
)
2126 switch (page_size
) {
2160 #if defined(TARGET_PPC64)
2161 case 0x000100000000ULL
:
2164 case 0x000400000000ULL
:
2167 case 0x001000000000ULL
:
2170 case 0x004000000000ULL
:
2173 case 0x010000000000ULL
:
2185 /* Helpers for 4xx TLB management */
2186 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2188 #define PPC4XX_TLBHI_V 0x00000040
2189 #define PPC4XX_TLBHI_E 0x00000020
2190 #define PPC4XX_TLBHI_SIZE_MIN 0
2191 #define PPC4XX_TLBHI_SIZE_MAX 7
2192 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2193 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2194 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2196 #define PPC4XX_TLBLO_EX 0x00000200
2197 #define PPC4XX_TLBLO_WR 0x00000100
2198 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2199 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2201 target_ulong
helper_4xx_tlbre_hi(CPUPPCState
*env
, target_ulong entry
)
2207 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2208 tlb
= &env
->tlb
.tlbe
[entry
];
2210 if (tlb
->prot
& PAGE_VALID
) {
2211 ret
|= PPC4XX_TLBHI_V
;
2213 size
= booke_page_size_to_tlb(tlb
->size
);
2214 if (size
< PPC4XX_TLBHI_SIZE_MIN
|| size
> PPC4XX_TLBHI_SIZE_MAX
) {
2215 size
= PPC4XX_TLBHI_SIZE_DEFAULT
;
2217 ret
|= size
<< PPC4XX_TLBHI_SIZE_SHIFT
;
2218 env
->spr
[SPR_40x_PID
] = tlb
->PID
;
2222 target_ulong
helper_4xx_tlbre_lo(CPUPPCState
*env
, target_ulong entry
)
2227 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2228 tlb
= &env
->tlb
.tlbe
[entry
];
2230 if (tlb
->prot
& PAGE_EXEC
) {
2231 ret
|= PPC4XX_TLBLO_EX
;
2233 if (tlb
->prot
& PAGE_WRITE
) {
2234 ret
|= PPC4XX_TLBLO_WR
;
2239 void helper_4xx_tlbwe_hi(CPUPPCState
*env
, target_ulong entry
,
2243 target_ulong page
, end
;
2245 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2247 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2248 tlb
= &env
->tlb
.tlbe
[entry
];
2249 /* Invalidate previous TLB (if it's valid) */
2250 if (tlb
->prot
& PAGE_VALID
) {
2251 end
= tlb
->EPN
+ tlb
->size
;
2252 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx
" end "
2253 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2254 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2255 tlb_flush_page(env
, page
);
2258 tlb
->size
= booke_tlb_to_page_size((val
>> PPC4XX_TLBHI_SIZE_SHIFT
)
2259 & PPC4XX_TLBHI_SIZE_MASK
);
2260 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2261 * If this ever occurs, one should use the ppcemb target instead
2262 * of the ppc or ppc64 one
2264 if ((val
& PPC4XX_TLBHI_V
) && tlb
->size
< TARGET_PAGE_SIZE
) {
2265 cpu_abort(env
, "TLB size " TARGET_FMT_lu
" < %u "
2266 "are not supported (%d)\n",
2267 tlb
->size
, TARGET_PAGE_SIZE
, (int)((val
>> 7) & 0x7));
2269 tlb
->EPN
= val
& ~(tlb
->size
- 1);
2270 if (val
& PPC4XX_TLBHI_V
) {
2271 tlb
->prot
|= PAGE_VALID
;
2272 if (val
& PPC4XX_TLBHI_E
) {
2273 /* XXX: TO BE FIXED */
2275 "Little-endian TLB entries are not supported by now\n");
2278 tlb
->prot
&= ~PAGE_VALID
;
2280 tlb
->PID
= env
->spr
[SPR_40x_PID
]; /* PID */
2281 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2282 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2283 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2284 tlb
->prot
& PAGE_READ
? 'r' : '-',
2285 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2286 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2287 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2288 /* Invalidate new TLB (if valid) */
2289 if (tlb
->prot
& PAGE_VALID
) {
2290 end
= tlb
->EPN
+ tlb
->size
;
2291 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx
" end "
2292 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2293 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2294 tlb_flush_page(env
, page
);
2299 void helper_4xx_tlbwe_lo(CPUPPCState
*env
, target_ulong entry
,
2304 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2306 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2307 tlb
= &env
->tlb
.tlbe
[entry
];
2308 tlb
->attr
= val
& PPC4XX_TLBLO_ATTR_MASK
;
2309 tlb
->RPN
= val
& PPC4XX_TLBLO_RPN_MASK
;
2310 tlb
->prot
= PAGE_READ
;
2311 if (val
& PPC4XX_TLBLO_EX
) {
2312 tlb
->prot
|= PAGE_EXEC
;
2314 if (val
& PPC4XX_TLBLO_WR
) {
2315 tlb
->prot
|= PAGE_WRITE
;
2317 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2318 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2319 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2320 tlb
->prot
& PAGE_READ
? 'r' : '-',
2321 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2322 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2323 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2326 target_ulong
helper_4xx_tlbsx(CPUPPCState
*env
, target_ulong address
)
2328 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_40x_PID
]);
2331 /* PowerPC 440 TLB management */
2332 void helper_440_tlbwe(CPUPPCState
*env
, uint32_t word
, target_ulong entry
,
2336 target_ulong EPN
, RPN
, size
;
2339 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx
"\n",
2340 __func__
, word
, (int)entry
, value
);
2343 tlb
= &env
->tlb
.tlbe
[entry
];
2346 /* Just here to please gcc */
2348 EPN
= value
& 0xFFFFFC00;
2349 if ((tlb
->prot
& PAGE_VALID
) && EPN
!= tlb
->EPN
) {
2353 size
= booke_tlb_to_page_size((value
>> 4) & 0xF);
2354 if ((tlb
->prot
& PAGE_VALID
) && tlb
->size
< size
) {
2359 tlb
->attr
|= (value
>> 8) & 1;
2360 if (value
& 0x200) {
2361 tlb
->prot
|= PAGE_VALID
;
2363 if (tlb
->prot
& PAGE_VALID
) {
2364 tlb
->prot
&= ~PAGE_VALID
;
2368 tlb
->PID
= env
->spr
[SPR_440_MMUCR
] & 0x000000FF;
2369 if (do_flush_tlbs
) {
2374 RPN
= value
& 0xFFFFFC0F;
2375 if ((tlb
->prot
& PAGE_VALID
) && tlb
->RPN
!= RPN
) {
2381 tlb
->attr
= (tlb
->attr
& 0x1) | (value
& 0x0000FF00);
2382 tlb
->prot
= tlb
->prot
& PAGE_VALID
;
2384 tlb
->prot
|= PAGE_READ
<< 4;
2387 tlb
->prot
|= PAGE_WRITE
<< 4;
2390 tlb
->prot
|= PAGE_EXEC
<< 4;
2393 tlb
->prot
|= PAGE_READ
;
2396 tlb
->prot
|= PAGE_WRITE
;
2399 tlb
->prot
|= PAGE_EXEC
;
2405 target_ulong
helper_440_tlbre(CPUPPCState
*env
, uint32_t word
,
2413 tlb
= &env
->tlb
.tlbe
[entry
];
2416 /* Just here to please gcc */
2419 size
= booke_page_size_to_tlb(tlb
->size
);
2420 if (size
< 0 || size
> 0xF) {
2424 if (tlb
->attr
& 0x1) {
2427 if (tlb
->prot
& PAGE_VALID
) {
2430 env
->spr
[SPR_440_MMUCR
] &= ~0x000000FF;
2431 env
->spr
[SPR_440_MMUCR
] |= tlb
->PID
;
2437 ret
= tlb
->attr
& ~0x1;
2438 if (tlb
->prot
& (PAGE_READ
<< 4)) {
2441 if (tlb
->prot
& (PAGE_WRITE
<< 4)) {
2444 if (tlb
->prot
& (PAGE_EXEC
<< 4)) {
2447 if (tlb
->prot
& PAGE_READ
) {
2450 if (tlb
->prot
& PAGE_WRITE
) {
2453 if (tlb
->prot
& PAGE_EXEC
) {
2461 target_ulong
helper_440_tlbsx(CPUPPCState
*env
, target_ulong address
)
2463 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_440_MMUCR
] & 0xFF);
2466 /* PowerPC BookE 2.06 TLB management */
2468 static ppcmas_tlb_t
*booke206_cur_tlb(CPUPPCState
*env
)
2470 uint32_t tlbncfg
= 0;
2471 int esel
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ESEL_MASK
) >> MAS0_ESEL_SHIFT
;
2472 int ea
= (env
->spr
[SPR_BOOKE_MAS2
] & MAS2_EPN_MASK
);
2475 tlb
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2476 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlb
];
2478 if ((tlbncfg
& TLBnCFG_HES
) && (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_HES
)) {
2479 cpu_abort(env
, "we don't support HES yet\n");
2482 return booke206_get_tlbm(env
, tlb
, ea
, esel
);
2485 void helper_booke_setpid(CPUPPCState
*env
, uint32_t pidn
, target_ulong pid
)
2487 env
->spr
[pidn
] = pid
;
2488 /* changing PIDs mean we're in a different address space now */
2492 void helper_booke206_tlbwe(CPUPPCState
*env
)
2494 uint32_t tlbncfg
, tlbn
;
2496 uint32_t size_tlb
, size_ps
;
2500 switch (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_WQ_MASK
) {
2501 case MAS0_WQ_ALWAYS
:
2502 /* good to go, write that entry */
2505 /* XXX check if reserved */
2510 case MAS0_WQ_CLR_RSRV
:
2511 /* XXX clear entry */
2514 /* no idea what to do */
2518 if (((env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ATSEL
) == MAS0_ATSEL_LRAT
) &&
2520 /* XXX we don't support direct LRAT setting yet */
2521 fprintf(stderr
, "cpu: don't support LRAT setting yet\n");
2525 tlbn
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2526 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlbn
];
2528 tlb
= booke206_cur_tlb(env
);
2531 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2532 POWERPC_EXCP_INVAL
|
2533 POWERPC_EXCP_INVAL_INVAL
);
2536 /* check that we support the targeted size */
2537 size_tlb
= (env
->spr
[SPR_BOOKE_MAS1
] & MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
2538 size_ps
= booke206_tlbnps(env
, tlbn
);
2539 if ((env
->spr
[SPR_BOOKE_MAS1
] & MAS1_VALID
) && (tlbncfg
& TLBnCFG_AVAIL
) &&
2540 !(size_ps
& (1 << size_tlb
))) {
2541 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2542 POWERPC_EXCP_INVAL
|
2543 POWERPC_EXCP_INVAL_INVAL
);
2547 cpu_abort(env
, "missing HV implementation\n");
2549 tlb
->mas7_3
= ((uint64_t)env
->spr
[SPR_BOOKE_MAS7
] << 32) |
2550 env
->spr
[SPR_BOOKE_MAS3
];
2551 tlb
->mas1
= env
->spr
[SPR_BOOKE_MAS1
];
2554 if (!(tlbncfg
& TLBnCFG_AVAIL
)) {
2555 /* force !AVAIL TLB entries to correct page size */
2556 tlb
->mas1
&= ~MAS1_TSIZE_MASK
;
2557 /* XXX can be configured in MMUCSR0 */
2558 tlb
->mas1
|= (tlbncfg
& TLBnCFG_MINSIZE
) >> 12;
2561 /* Make a mask from TLB size to discard invalid bits in EPN field */
2562 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2563 /* Add a mask for page attributes */
2564 mask
|= MAS2_ACM
| MAS2_VLE
| MAS2_W
| MAS2_I
| MAS2_M
| MAS2_G
| MAS2_E
;
2567 /* Executing a tlbwe instruction in 32-bit mode will set
2568 * bits 0:31 of the TLB EPN field to zero.
2573 tlb
->mas2
= env
->spr
[SPR_BOOKE_MAS2
] & mask
;
2575 if (!(tlbncfg
& TLBnCFG_IPROT
)) {
2576 /* no IPROT supported by TLB */
2577 tlb
->mas1
&= ~MAS1_IPROT
;
2580 if (booke206_tlb_to_page_size(env
, tlb
) == TARGET_PAGE_SIZE
) {
2581 tlb_flush_page(env
, tlb
->mas2
& MAS2_EPN_MASK
);
2587 static inline void booke206_tlb_to_mas(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2589 int tlbn
= booke206_tlbm_to_tlbn(env
, tlb
);
2590 int way
= booke206_tlbm_to_way(env
, tlb
);
2592 env
->spr
[SPR_BOOKE_MAS0
] = tlbn
<< MAS0_TLBSEL_SHIFT
;
2593 env
->spr
[SPR_BOOKE_MAS0
] |= way
<< MAS0_ESEL_SHIFT
;
2594 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2596 env
->spr
[SPR_BOOKE_MAS1
] = tlb
->mas1
;
2597 env
->spr
[SPR_BOOKE_MAS2
] = tlb
->mas2
;
2598 env
->spr
[SPR_BOOKE_MAS3
] = tlb
->mas7_3
;
2599 env
->spr
[SPR_BOOKE_MAS7
] = tlb
->mas7_3
>> 32;
2602 void helper_booke206_tlbre(CPUPPCState
*env
)
2604 ppcmas_tlb_t
*tlb
= NULL
;
2606 tlb
= booke206_cur_tlb(env
);
2608 env
->spr
[SPR_BOOKE_MAS1
] = 0;
2610 booke206_tlb_to_mas(env
, tlb
);
2614 void helper_booke206_tlbsx(CPUPPCState
*env
, target_ulong address
)
2616 ppcmas_tlb_t
*tlb
= NULL
;
2621 spid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID_MASK
) >> MAS6_SPID_SHIFT
;
2622 sas
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
;
2624 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2625 int ways
= booke206_tlb_ways(env
, i
);
2627 for (j
= 0; j
< ways
; j
++) {
2628 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2634 if (ppcmas_tlb_check(env
, tlb
, &raddr
, address
, spid
)) {
2638 if (sas
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
2642 booke206_tlb_to_mas(env
, tlb
);
2647 /* no entry found, fill with defaults */
2648 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
2649 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
2650 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
2651 env
->spr
[SPR_BOOKE_MAS3
] = 0;
2652 env
->spr
[SPR_BOOKE_MAS7
] = 0;
2654 if (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
) {
2655 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
2658 env
->spr
[SPR_BOOKE_MAS1
] |= (env
->spr
[SPR_BOOKE_MAS6
] >> 16)
2661 /* next victim logic */
2662 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
2664 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
2665 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2668 static inline void booke206_invalidate_ea_tlb(CPUPPCState
*env
, int tlbn
,
2672 int ways
= booke206_tlb_ways(env
, tlbn
);
2675 for (i
= 0; i
< ways
; i
++) {
2676 ppcmas_tlb_t
*tlb
= booke206_get_tlbm(env
, tlbn
, ea
, i
);
2680 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2681 if (((tlb
->mas2
& MAS2_EPN_MASK
) == (ea
& mask
)) &&
2682 !(tlb
->mas1
& MAS1_IPROT
)) {
2683 tlb
->mas1
&= ~MAS1_VALID
;
2688 void helper_booke206_tlbivax(CPUPPCState
*env
, target_ulong address
)
2690 if (address
& 0x4) {
2691 /* flush all entries */
2692 if (address
& 0x8) {
2693 /* flush all of TLB1 */
2694 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB1
, 1);
2696 /* flush all of TLB0 */
2697 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB0
, 0);
2702 if (address
& 0x8) {
2703 /* flush TLB1 entries */
2704 booke206_invalidate_ea_tlb(env
, 1, address
);
2707 /* flush TLB0 entries */
2708 booke206_invalidate_ea_tlb(env
, 0, address
);
2709 tlb_flush_page(env
, address
& MAS2_EPN_MASK
);
2713 void helper_booke206_tlbilx0(CPUPPCState
*env
, target_ulong address
)
2715 /* XXX missing LPID handling */
2716 booke206_flush_tlb(env
, -1, 1);
2719 void helper_booke206_tlbilx1(CPUPPCState
*env
, target_ulong address
)
2722 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2723 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
2726 /* XXX missing LPID handling */
2727 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2728 tlb_size
= booke206_tlb_size(env
, i
);
2729 for (j
= 0; j
< tlb_size
; j
++) {
2730 if (!(tlb
[j
].mas1
& MAS1_IPROT
) &&
2731 ((tlb
[j
].mas1
& MAS1_TID_MASK
) == tid
)) {
2732 tlb
[j
].mas1
&= ~MAS1_VALID
;
2735 tlb
+= booke206_tlb_size(env
, i
);
2740 void helper_booke206_tlbilx3(CPUPPCState
*env
, target_ulong address
)
2744 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2745 int pid
= tid
>> MAS6_SPID_SHIFT
;
2746 int sgs
= env
->spr
[SPR_BOOKE_MAS5
] & MAS5_SGS
;
2747 int ind
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SIND
) ? MAS1_IND
: 0;
2748 /* XXX check for unsupported isize and raise an invalid opcode then */
2749 int size
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_ISIZE_MASK
;
2750 /* XXX implement MAV2 handling */
2753 /* XXX missing LPID handling */
2754 /* flush by pid and ea */
2755 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2756 int ways
= booke206_tlb_ways(env
, i
);
2758 for (j
= 0; j
< ways
; j
++) {
2759 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2763 if ((ppcmas_tlb_check(env
, tlb
, NULL
, address
, pid
) != 0) ||
2764 (tlb
->mas1
& MAS1_IPROT
) ||
2765 ((tlb
->mas1
& MAS1_IND
) != ind
) ||
2766 ((tlb
->mas8
& MAS8_TGS
) != sgs
)) {
2769 if (mav2
&& ((tlb
->mas1
& MAS1_TSIZE_MASK
) != size
)) {
2770 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2773 /* XXX e500mc doesn't match SAS, but other cores might */
2774 tlb
->mas1
&= ~MAS1_VALID
;
2780 void helper_booke206_tlbflush(CPUPPCState
*env
, uint32_t type
)
2785 flags
|= BOOKE206_FLUSH_TLB1
;
2789 flags
|= BOOKE206_FLUSH_TLB0
;
2792 booke206_flush_tlb(env
, flags
, 1);