2 * PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "sysemu/kvm.h"
23 #include "mmu-hash64.h"
24 #include "mmu-hash32.h"
28 //#define DEBUG_SOFTWARE_TLB
29 //#define DUMP_PAGE_TABLES
30 //#define DEBUG_SOFTWARE_TLB
31 //#define FLUSH_ALL_TLBS
34 # define LOG_MMU(...) qemu_log(__VA_ARGS__)
35 # define LOG_MMU_STATE(cpu) log_cpu_state((cpu), 0)
37 # define LOG_MMU(...) do { } while (0)
38 # define LOG_MMU_STATE(cpu) do { } while (0)
41 #ifdef DEBUG_SOFTWARE_TLB
42 # define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
44 # define LOG_SWTLB(...) do { } while (0)
48 # define LOG_BATS(...) qemu_log(__VA_ARGS__)
50 # define LOG_BATS(...) do { } while (0)
53 /*****************************************************************************/
54 /* PowerPC MMU emulation */
56 /* Context used internally during MMU translations */
57 typedef struct mmu_ctx_t mmu_ctx_t
;
59 hwaddr raddr
; /* Real address */
60 hwaddr eaddr
; /* Effective address */
61 int prot
; /* Protection bits */
62 hwaddr hash
[2]; /* Pagetable hash values */
63 target_ulong ptem
; /* Virtual segment ID | API */
64 int key
; /* Access key */
65 int nx
; /* Non-execute area */
68 /* Common routines used by software and hardware TLBs emulation */
69 static inline int pte_is_valid(target_ulong pte0
)
71 return pte0
& 0x80000000 ? 1 : 0;
74 static inline void pte_invalidate(target_ulong
*pte0
)
79 #define PTE_PTEM_MASK 0x7FFFFFBF
80 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
82 static int pp_check(int key
, int pp
, int nx
)
86 /* Compute access rights */
109 access
= PAGE_READ
| PAGE_WRITE
;
120 static int check_prot(int prot
, int rw
, int access_type
)
124 if (access_type
== ACCESS_CODE
) {
125 if (prot
& PAGE_EXEC
) {
131 if (prot
& PAGE_WRITE
) {
137 if (prot
& PAGE_READ
) {
147 static inline int ppc6xx_tlb_pte_check(mmu_ctx_t
*ctx
, target_ulong pte0
,
148 target_ulong pte1
, int h
, int rw
, int type
)
150 target_ulong ptem
, mmask
;
151 int access
, ret
, pteh
, ptev
, pp
;
154 /* Check validity and table match */
155 ptev
= pte_is_valid(pte0
);
156 pteh
= (pte0
>> 6) & 1;
157 if (ptev
&& h
== pteh
) {
158 /* Check vsid & api */
159 ptem
= pte0
& PTE_PTEM_MASK
;
160 mmask
= PTE_CHECK_MASK
;
161 pp
= pte1
& 0x00000003;
162 if (ptem
== ctx
->ptem
) {
163 if (ctx
->raddr
!= (hwaddr
)-1ULL) {
164 /* all matches should have equal RPN, WIMG & PP */
165 if ((ctx
->raddr
& mmask
) != (pte1
& mmask
)) {
166 qemu_log("Bad RPN/WIMG/PP\n");
170 /* Compute access rights */
171 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
172 /* Keep the matching PTE informations */
175 ret
= check_prot(ctx
->prot
, rw
, type
);
178 LOG_MMU("PTE access granted !\n");
180 /* Access right violation */
181 LOG_MMU("PTE access rejected\n");
189 static int pte_update_flags(mmu_ctx_t
*ctx
, target_ulong
*pte1p
,
194 /* Update page flags */
195 if (!(*pte1p
& 0x00000100)) {
196 /* Update accessed flag */
197 *pte1p
|= 0x00000100;
200 if (!(*pte1p
& 0x00000080)) {
201 if (rw
== 1 && ret
== 0) {
202 /* Update changed flag */
203 *pte1p
|= 0x00000080;
206 /* Force page fault for first write access */
207 ctx
->prot
&= ~PAGE_WRITE
;
214 /* Software driven TLB helpers */
215 static inline int ppc6xx_tlb_getnum(CPUPPCState
*env
, target_ulong eaddr
,
216 int way
, int is_code
)
220 /* Select TLB num in a way from address */
221 nr
= (eaddr
>> TARGET_PAGE_BITS
) & (env
->tlb_per_way
- 1);
223 nr
+= env
->tlb_per_way
* way
;
224 /* 6xx have separate TLBs for instructions and data */
225 if (is_code
&& env
->id_tlbs
== 1) {
232 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState
*env
)
234 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
238 /* LOG_SWTLB("Invalidate all TLBs\n"); */
239 /* Invalidate all defined software TLB */
241 if (env
->id_tlbs
== 1) {
244 for (nr
= 0; nr
< max
; nr
++) {
245 tlb
= &env
->tlb
.tlb6
[nr
];
246 pte_invalidate(&tlb
->pte0
);
248 tlb_flush(CPU(cpu
), 1);
251 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState
*env
,
253 int is_code
, int match_epn
)
255 #if !defined(FLUSH_ALL_TLBS)
256 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
260 /* Invalidate ITLB + DTLB, all ways */
261 for (way
= 0; way
< env
->nb_ways
; way
++) {
262 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
, is_code
);
263 tlb
= &env
->tlb
.tlb6
[nr
];
264 if (pte_is_valid(tlb
->pte0
) && (match_epn
== 0 || eaddr
== tlb
->EPN
)) {
265 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx
"\n", nr
,
267 pte_invalidate(&tlb
->pte0
);
268 tlb_flush_page(cs
, tlb
->EPN
);
272 /* XXX: PowerPC specification say this is valid as well */
273 ppc6xx_tlb_invalidate_all(env
);
277 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState
*env
,
278 target_ulong eaddr
, int is_code
)
280 ppc6xx_tlb_invalidate_virt2(env
, eaddr
, is_code
, 0);
283 static void ppc6xx_tlb_store(CPUPPCState
*env
, target_ulong EPN
, int way
,
284 int is_code
, target_ulong pte0
, target_ulong pte1
)
289 nr
= ppc6xx_tlb_getnum(env
, EPN
, way
, is_code
);
290 tlb
= &env
->tlb
.tlb6
[nr
];
291 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
292 " PTE1 " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
, EPN
, pte0
, pte1
);
293 /* Invalidate any pending reference in QEMU for this virtual address */
294 ppc6xx_tlb_invalidate_virt2(env
, EPN
, is_code
, 1);
298 /* Store last way for LRU mechanism */
302 static inline int ppc6xx_tlb_check(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
303 target_ulong eaddr
, int rw
, int access_type
)
310 ret
= -1; /* No TLB found */
311 for (way
= 0; way
< env
->nb_ways
; way
++) {
312 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
,
313 access_type
== ACCESS_CODE
? 1 : 0);
314 tlb
= &env
->tlb
.tlb6
[nr
];
315 /* This test "emulates" the PTE index match for hardware TLBs */
316 if ((eaddr
& TARGET_PAGE_MASK
) != tlb
->EPN
) {
317 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx
" " TARGET_FMT_lx
318 "] <> " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
,
319 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
320 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
, eaddr
);
323 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx
" <> " TARGET_FMT_lx
" "
324 TARGET_FMT_lx
" %c %c\n", nr
, env
->nb_tlb
,
325 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
326 tlb
->EPN
, eaddr
, tlb
->pte1
,
327 rw
? 'S' : 'L', access_type
== ACCESS_CODE
? 'I' : 'D');
328 switch (ppc6xx_tlb_pte_check(ctx
, tlb
->pte0
, tlb
->pte1
, 0, rw
, access_type
)) {
330 /* TLB inconsistency */
333 /* Access violation */
343 /* XXX: we should go on looping to check all TLBs consistency
344 * but we can speed-up the whole thing as the
345 * result would be undefined if TLBs are not consistent.
354 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx
" prot=%01x ret=%d\n",
355 ctx
->raddr
& TARGET_PAGE_MASK
, ctx
->prot
, ret
);
356 /* Update page flags */
357 pte_update_flags(ctx
, &env
->tlb
.tlb6
[best
].pte1
, ret
, rw
);
363 /* Perform BAT hit & translation */
364 static inline void bat_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
365 int *validp
, int *protp
, target_ulong
*BATu
,
371 bl
= (*BATu
& 0x00001FFC) << 15;
374 if (((msr_pr
== 0) && (*BATu
& 0x00000002)) ||
375 ((msr_pr
!= 0) && (*BATu
& 0x00000001))) {
377 pp
= *BATl
& 0x00000003;
379 prot
= PAGE_READ
| PAGE_EXEC
;
390 static int get_bat_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
391 target_ulong
virtual, int rw
, int type
)
393 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
394 target_ulong BEPIl
, BEPIu
, bl
;
398 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx
"\n", __func__
,
399 type
== ACCESS_CODE
? 'I' : 'D', virtual);
402 BATlt
= env
->IBAT
[1];
403 BATut
= env
->IBAT
[0];
406 BATlt
= env
->DBAT
[1];
407 BATut
= env
->DBAT
[0];
410 for (i
= 0; i
< env
->nb_BATs
; i
++) {
413 BEPIu
= *BATu
& 0xF0000000;
414 BEPIl
= *BATu
& 0x0FFE0000;
415 bat_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
416 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
417 " BATl " TARGET_FMT_lx
"\n", __func__
,
418 type
== ACCESS_CODE
? 'I' : 'D', i
, virtual, *BATu
, *BATl
);
419 if ((virtual & 0xF0000000) == BEPIu
&&
420 ((virtual & 0x0FFE0000) & ~bl
) == BEPIl
) {
423 /* Get physical address */
424 ctx
->raddr
= (*BATl
& 0xF0000000) |
425 ((virtual & 0x0FFE0000 & bl
) | (*BATl
& 0x0FFE0000)) |
426 (virtual & 0x0001F000);
427 /* Compute access rights */
429 ret
= check_prot(ctx
->prot
, rw
, type
);
431 LOG_BATS("BAT %d match: r " TARGET_FMT_plx
" prot=%c%c\n",
432 i
, ctx
->raddr
, ctx
->prot
& PAGE_READ
? 'R' : '-',
433 ctx
->prot
& PAGE_WRITE
? 'W' : '-');
440 #if defined(DEBUG_BATS)
441 if (qemu_log_enabled()) {
442 LOG_BATS("no BAT match for " TARGET_FMT_lx
":\n", virtual);
443 for (i
= 0; i
< 4; i
++) {
446 BEPIu
= *BATu
& 0xF0000000;
447 BEPIl
= *BATu
& 0x0FFE0000;
448 bl
= (*BATu
& 0x00001FFC) << 15;
449 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
450 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
451 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
452 __func__
, type
== ACCESS_CODE
? 'I' : 'D', i
, virtual,
453 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
462 /* Perform segment based translation */
463 static inline int get_segment_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
464 target_ulong eaddr
, int rw
, int type
)
468 int ds
, pr
, target_page_bits
;
470 target_ulong sr
, pgidx
;
475 sr
= env
->sr
[eaddr
>> 28];
476 ctx
->key
= (((sr
& 0x20000000) && (pr
!= 0)) ||
477 ((sr
& 0x40000000) && (pr
== 0))) ? 1 : 0;
478 ds
= sr
& 0x80000000 ? 1 : 0;
479 ctx
->nx
= sr
& 0x10000000 ? 1 : 0;
480 vsid
= sr
& 0x00FFFFFF;
481 target_page_bits
= TARGET_PAGE_BITS
;
482 LOG_MMU("Check segment v=" TARGET_FMT_lx
" %d " TARGET_FMT_lx
" nip="
483 TARGET_FMT_lx
" lr=" TARGET_FMT_lx
484 " ir=%d dr=%d pr=%d %d t=%d\n",
485 eaddr
, (int)(eaddr
>> 28), sr
, env
->nip
, env
->lr
, (int)msr_ir
,
486 (int)msr_dr
, pr
!= 0 ? 1 : 0, rw
, type
);
487 pgidx
= (eaddr
& ~SEGMENT_MASK_256M
) >> target_page_bits
;
489 ctx
->ptem
= (vsid
<< 7) | (pgidx
>> 10);
491 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx
"\n",
492 ctx
->key
, ds
, ctx
->nx
, vsid
);
495 /* Check if instruction fetch is allowed, if needed */
496 if (type
!= ACCESS_CODE
|| ctx
->nx
== 0) {
497 /* Page address translation */
498 LOG_MMU("htab_base " TARGET_FMT_plx
" htab_mask " TARGET_FMT_plx
499 " hash " TARGET_FMT_plx
"\n",
500 env
->htab_base
, env
->htab_mask
, hash
);
502 ctx
->hash
[1] = ~hash
;
504 /* Initialize real address with an invalid value */
505 ctx
->raddr
= (hwaddr
)-1ULL;
506 /* Software TLB search */
507 ret
= ppc6xx_tlb_check(env
, ctx
, eaddr
, rw
, type
);
508 #if defined(DUMP_PAGE_TABLES)
509 if (qemu_log_enabled()) {
511 uint32_t a0
, a1
, a2
, a3
;
513 qemu_log("Page table: " TARGET_FMT_plx
" len " TARGET_FMT_plx
514 "\n", sdr
, mask
+ 0x80);
515 for (curaddr
= sdr
; curaddr
< (sdr
+ mask
+ 0x80);
517 a0
= ldl_phys(curaddr
);
518 a1
= ldl_phys(curaddr
+ 4);
519 a2
= ldl_phys(curaddr
+ 8);
520 a3
= ldl_phys(curaddr
+ 12);
521 if (a0
!= 0 || a1
!= 0 || a2
!= 0 || a3
!= 0) {
522 qemu_log(TARGET_FMT_plx
": %08x %08x %08x %08x\n",
523 curaddr
, a0
, a1
, a2
, a3
);
529 LOG_MMU("No access allowed\n");
535 LOG_MMU("direct store...\n");
536 /* Direct-store segment : absolutely *BUGGY* for now */
538 /* Direct-store implies a 32-bit MMU.
539 * Check the Segment Register's bus unit ID (BUID).
541 sr
= env
->sr
[eaddr
>> 28];
542 if ((sr
& 0x1FF00000) >> 20 == 0x07f) {
543 /* Memory-forced I/O controller interface access */
544 /* If T=1 and BUID=x'07F', the 601 performs a memory access
545 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
547 ctx
->raddr
= ((sr
& 0xF) << 28) | (eaddr
& 0x0FFFFFFF);
548 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
554 /* Integer load/store : only access allowed */
557 /* No code fetch is allowed in direct-store areas */
560 /* Floating point load/store */
563 /* lwarx, ldarx or srwcx. */
566 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
567 /* Should make the instruction do no-op.
568 * As it already do no-op, it's quite easy :-)
576 qemu_log("ERROR: instruction should not need "
577 "address translation\n");
580 if ((rw
== 1 || ctx
->key
!= 1) && (rw
== 0 || ctx
->key
!= 0)) {
591 /* Generic TLB check function for embedded PowerPC implementations */
592 static int ppcemb_tlb_check(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
594 target_ulong address
, uint32_t pid
, int ext
,
599 /* Check valid flag */
600 if (!(tlb
->prot
& PAGE_VALID
)) {
603 mask
= ~(tlb
->size
- 1);
604 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx
" PID %u <=> " TARGET_FMT_lx
605 " " TARGET_FMT_lx
" %u %x\n", __func__
, i
, address
, pid
, tlb
->EPN
,
606 mask
, (uint32_t)tlb
->PID
, tlb
->prot
);
608 if (tlb
->PID
!= 0 && tlb
->PID
!= pid
) {
611 /* Check effective address */
612 if ((address
& mask
) != tlb
->EPN
) {
615 *raddrp
= (tlb
->RPN
& mask
) | (address
& ~mask
);
617 /* Extend the physical address to 36 bits */
618 *raddrp
|= (uint64_t)(tlb
->RPN
& 0xF) << 32;
624 /* Generic TLB search function for PowerPC embedded implementations */
625 static int ppcemb_tlb_search(CPUPPCState
*env
, target_ulong address
,
632 /* Default return value is no match */
634 for (i
= 0; i
< env
->nb_tlb
; i
++) {
635 tlb
= &env
->tlb
.tlbe
[i
];
636 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
, pid
, 0, i
) == 0) {
645 /* Helpers specific to PowerPC 40x implementations */
646 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState
*env
)
648 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
652 for (i
= 0; i
< env
->nb_tlb
; i
++) {
653 tlb
= &env
->tlb
.tlbe
[i
];
654 tlb
->prot
&= ~PAGE_VALID
;
656 tlb_flush(CPU(cpu
), 1);
659 static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState
*env
,
660 target_ulong eaddr
, uint32_t pid
)
662 #if !defined(FLUSH_ALL_TLBS)
663 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
666 target_ulong page
, end
;
669 for (i
= 0; i
< env
->nb_tlb
; i
++) {
670 tlb
= &env
->tlb
.tlbe
[i
];
671 if (ppcemb_tlb_check(env
, tlb
, &raddr
, eaddr
, pid
, 0, i
) == 0) {
672 end
= tlb
->EPN
+ tlb
->size
;
673 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
674 tlb_flush_page(cs
, page
);
676 tlb
->prot
&= ~PAGE_VALID
;
681 ppc4xx_tlb_invalidate_all(env
);
685 static int mmu40x_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
686 target_ulong address
, int rw
,
691 int i
, ret
, zsel
, zpr
, pr
;
694 raddr
= (hwaddr
)-1ULL;
696 for (i
= 0; i
< env
->nb_tlb
; i
++) {
697 tlb
= &env
->tlb
.tlbe
[i
];
698 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
699 env
->spr
[SPR_40x_PID
], 0, i
) < 0) {
702 zsel
= (tlb
->attr
>> 4) & 0xF;
703 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (30 - (2 * zsel
))) & 0x3;
704 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
705 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
706 /* Check execute enable bit */
714 /* All accesses granted */
715 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
720 /* Raise Zone protection fault. */
721 env
->spr
[SPR_40x_ESR
] = 1 << 22;
729 /* Check from TLB entry */
730 ctx
->prot
= tlb
->prot
;
731 ret
= check_prot(ctx
->prot
, rw
, access_type
);
733 env
->spr
[SPR_40x_ESR
] = 0;
739 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
740 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
745 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
746 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
751 void store_40x_sler(CPUPPCState
*env
, uint32_t val
)
753 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
755 /* XXX: TO BE FIXED */
756 if (val
!= 0x00000000) {
757 cpu_abort(CPU(cpu
), "Little-endian regions are not supported by now\n");
759 env
->spr
[SPR_405_SLER
] = val
;
762 static inline int mmubooke_check_tlb(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
763 hwaddr
*raddr
, int *prot
,
764 target_ulong address
, int rw
,
765 int access_type
, int i
)
769 if (ppcemb_tlb_check(env
, tlb
, raddr
, address
,
770 env
->spr
[SPR_BOOKE_PID
],
771 !env
->nb_pids
, i
) >= 0) {
775 if (env
->spr
[SPR_BOOKE_PID1
] &&
776 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
777 env
->spr
[SPR_BOOKE_PID1
], 0, i
) >= 0) {
781 if (env
->spr
[SPR_BOOKE_PID2
] &&
782 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
783 env
->spr
[SPR_BOOKE_PID2
], 0, i
) >= 0) {
787 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
793 prot2
= tlb
->prot
& 0xF;
795 prot2
= (tlb
->prot
>> 4) & 0xF;
798 /* Check the address space */
799 if (access_type
== ACCESS_CODE
) {
800 if (msr_ir
!= (tlb
->attr
& 1)) {
801 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
806 if (prot2
& PAGE_EXEC
) {
807 LOG_SWTLB("%s: good TLB!\n", __func__
);
811 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
814 if (msr_dr
!= (tlb
->attr
& 1)) {
815 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
820 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
821 LOG_SWTLB("%s: found TLB!\n", __func__
);
825 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
832 static int mmubooke_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
833 target_ulong address
, int rw
,
841 raddr
= (hwaddr
)-1ULL;
842 for (i
= 0; i
< env
->nb_tlb
; i
++) {
843 tlb
= &env
->tlb
.tlbe
[i
];
844 ret
= mmubooke_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
, rw
,
853 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
854 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
857 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
858 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
864 static void booke206_flush_tlb(CPUPPCState
*env
, int flags
,
865 const int check_iprot
)
867 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
870 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
872 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
873 if (flags
& (1 << i
)) {
874 tlb_size
= booke206_tlb_size(env
, i
);
875 for (j
= 0; j
< tlb_size
; j
++) {
876 if (!check_iprot
|| !(tlb
[j
].mas1
& MAS1_IPROT
)) {
877 tlb
[j
].mas1
&= ~MAS1_VALID
;
881 tlb
+= booke206_tlb_size(env
, i
);
884 tlb_flush(CPU(cpu
), 1);
887 static hwaddr
booke206_tlb_to_page_size(CPUPPCState
*env
,
892 tlbm_size
= (tlb
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
894 return 1024ULL << tlbm_size
;
897 /* TLB check function for MAS based SoftTLBs */
898 static int ppcmas_tlb_check(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
900 target_ulong address
, uint32_t pid
)
905 /* Check valid flag */
906 if (!(tlb
->mas1
& MAS1_VALID
)) {
910 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
911 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx
" PID=0x%x MAS1=0x%x MAS2=0x%"
912 PRIx64
" mask=0x" TARGET_FMT_lx
" MAS7_3=0x%" PRIx64
" MAS8=%x\n",
913 __func__
, address
, pid
, tlb
->mas1
, tlb
->mas2
, mask
, tlb
->mas7_3
,
917 tlb_pid
= (tlb
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
;
918 if (tlb_pid
!= 0 && tlb_pid
!= pid
) {
922 /* Check effective address */
923 if ((address
& mask
) != (tlb
->mas2
& MAS2_EPN_MASK
)) {
928 *raddrp
= (tlb
->mas7_3
& mask
) | (address
& ~mask
);
934 static int mmubooke206_check_tlb(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
935 hwaddr
*raddr
, int *prot
,
936 target_ulong address
, int rw
,
942 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
,
943 env
->spr
[SPR_BOOKE_PID
]) >= 0) {
947 if (env
->spr
[SPR_BOOKE_PID1
] &&
948 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
949 env
->spr
[SPR_BOOKE_PID1
]) >= 0) {
953 if (env
->spr
[SPR_BOOKE_PID2
] &&
954 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
955 env
->spr
[SPR_BOOKE_PID2
]) >= 0) {
959 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
965 if (tlb
->mas7_3
& MAS3_UR
) {
968 if (tlb
->mas7_3
& MAS3_UW
) {
971 if (tlb
->mas7_3
& MAS3_UX
) {
975 if (tlb
->mas7_3
& MAS3_SR
) {
978 if (tlb
->mas7_3
& MAS3_SW
) {
981 if (tlb
->mas7_3
& MAS3_SX
) {
986 /* Check the address space and permissions */
987 if (access_type
== ACCESS_CODE
) {
988 if (msr_ir
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
989 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
994 if (prot2
& PAGE_EXEC
) {
995 LOG_SWTLB("%s: good TLB!\n", __func__
);
999 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
1002 if (msr_dr
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1003 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1008 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
1009 LOG_SWTLB("%s: found TLB!\n", __func__
);
1013 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
1020 static int mmubooke206_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1021 target_ulong address
, int rw
,
1029 raddr
= (hwaddr
)-1ULL;
1031 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1032 int ways
= booke206_tlb_ways(env
, i
);
1034 for (j
= 0; j
< ways
; j
++) {
1035 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
1039 ret
= mmubooke206_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
,
1051 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
1052 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1055 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
1056 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
1062 static const char *book3e_tsize_to_str
[32] = {
1063 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1064 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1065 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1069 static void mmubooke_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1072 ppcemb_tlb_t
*entry
;
1075 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1076 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1080 cpu_fprintf(f
, "\nTLB:\n");
1081 cpu_fprintf(f
, "Effective Physical Size PID Prot "
1084 entry
= &env
->tlb
.tlbe
[0];
1085 for (i
= 0; i
< env
->nb_tlb
; i
++, entry
++) {
1088 uint64_t size
= (uint64_t)entry
->size
;
1091 /* Check valid flag */
1092 if (!(entry
->prot
& PAGE_VALID
)) {
1096 mask
= ~(entry
->size
- 1);
1097 ea
= entry
->EPN
& mask
;
1098 pa
= entry
->RPN
& mask
;
1099 /* Extend the physical address to 36 bits */
1100 pa
|= (hwaddr
)(entry
->RPN
& 0xF) << 32;
1103 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"M", size
/ 1024);
1105 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"k", size
);
1107 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %s %-5u %08x %08x\n",
1108 (uint64_t)ea
, (uint64_t)pa
, size_buf
, (uint32_t)entry
->PID
,
1109 entry
->prot
, entry
->attr
);
1114 static void mmubooke206_dump_one_tlb(FILE *f
, fprintf_function cpu_fprintf
,
1115 CPUPPCState
*env
, int tlbn
, int offset
,
1118 ppcmas_tlb_t
*entry
;
1121 cpu_fprintf(f
, "\nTLB%d:\n", tlbn
);
1122 cpu_fprintf(f
, "Effective Physical Size TID TS SRWX"
1123 " URWX WIMGE U0123\n");
1125 entry
= &env
->tlb
.tlbm
[offset
];
1126 for (i
= 0; i
< tlbsize
; i
++, entry
++) {
1127 hwaddr ea
, pa
, size
;
1130 if (!(entry
->mas1
& MAS1_VALID
)) {
1134 tsize
= (entry
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1135 size
= 1024ULL << tsize
;
1136 ea
= entry
->mas2
& ~(size
- 1);
1137 pa
= entry
->mas7_3
& ~(size
- 1);
1139 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %4s %-5u %1u S%c%c%c"
1140 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1141 (uint64_t)ea
, (uint64_t)pa
,
1142 book3e_tsize_to_str
[tsize
],
1143 (entry
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
,
1144 (entry
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
,
1145 entry
->mas7_3
& MAS3_SR
? 'R' : '-',
1146 entry
->mas7_3
& MAS3_SW
? 'W' : '-',
1147 entry
->mas7_3
& MAS3_SX
? 'X' : '-',
1148 entry
->mas7_3
& MAS3_UR
? 'R' : '-',
1149 entry
->mas7_3
& MAS3_UW
? 'W' : '-',
1150 entry
->mas7_3
& MAS3_UX
? 'X' : '-',
1151 entry
->mas2
& MAS2_W
? 'W' : '-',
1152 entry
->mas2
& MAS2_I
? 'I' : '-',
1153 entry
->mas2
& MAS2_M
? 'M' : '-',
1154 entry
->mas2
& MAS2_G
? 'G' : '-',
1155 entry
->mas2
& MAS2_E
? 'E' : '-',
1156 entry
->mas7_3
& MAS3_U0
? '0' : '-',
1157 entry
->mas7_3
& MAS3_U1
? '1' : '-',
1158 entry
->mas7_3
& MAS3_U2
? '2' : '-',
1159 entry
->mas7_3
& MAS3_U3
? '3' : '-');
1163 static void mmubooke206_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1169 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1170 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1174 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1175 int size
= booke206_tlb_size(env
, i
);
1181 mmubooke206_dump_one_tlb(f
, cpu_fprintf
, env
, i
, offset
, size
);
1186 static void mmu6xx_dump_BATs(FILE *f
, fprintf_function cpu_fprintf
,
1187 CPUPPCState
*env
, int type
)
1189 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
1190 target_ulong BEPIl
, BEPIu
, bl
;
1195 BATlt
= env
->IBAT
[1];
1196 BATut
= env
->IBAT
[0];
1199 BATlt
= env
->DBAT
[1];
1200 BATut
= env
->DBAT
[0];
1204 for (i
= 0; i
< env
->nb_BATs
; i
++) {
1207 BEPIu
= *BATu
& 0xF0000000;
1208 BEPIl
= *BATu
& 0x0FFE0000;
1209 bl
= (*BATu
& 0x00001FFC) << 15;
1210 cpu_fprintf(f
, "%s BAT%d BATu " TARGET_FMT_lx
1211 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
1212 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
1213 type
== ACCESS_CODE
? "code" : "data", i
,
1214 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
1218 static void mmu6xx_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1223 int type
, way
, entry
, i
;
1225 cpu_fprintf(f
, "HTAB base = 0x%"HWADDR_PRIx
"\n", env
->htab_base
);
1226 cpu_fprintf(f
, "HTAB mask = 0x%"HWADDR_PRIx
"\n", env
->htab_mask
);
1228 cpu_fprintf(f
, "\nSegment registers:\n");
1229 for (i
= 0; i
< 32; i
++) {
1231 if (sr
& 0x80000000) {
1232 cpu_fprintf(f
, "%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1233 "CNTLR_SPEC=0x%05x\n", i
,
1234 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1235 sr
& 0x20000000 ? 1 : 0, (uint32_t)((sr
>> 20) & 0x1FF),
1236 (uint32_t)(sr
& 0xFFFFF));
1238 cpu_fprintf(f
, "%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i
,
1239 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1240 sr
& 0x20000000 ? 1 : 0, sr
& 0x10000000 ? 1 : 0,
1241 (uint32_t)(sr
& 0x00FFFFFF));
1245 cpu_fprintf(f
, "\nBATs:\n");
1246 mmu6xx_dump_BATs(f
, cpu_fprintf
, env
, ACCESS_INT
);
1247 mmu6xx_dump_BATs(f
, cpu_fprintf
, env
, ACCESS_CODE
);
1249 if (env
->id_tlbs
!= 1) {
1250 cpu_fprintf(f
, "ERROR: 6xx MMU should have separated TLB"
1251 " for code and data\n");
1254 cpu_fprintf(f
, "\nTLBs [EPN EPN + SIZE]\n");
1256 for (type
= 0; type
< 2; type
++) {
1257 for (way
= 0; way
< env
->nb_ways
; way
++) {
1258 for (entry
= env
->nb_tlb
* type
+ env
->tlb_per_way
* way
;
1259 entry
< (env
->nb_tlb
* type
+ env
->tlb_per_way
* (way
+ 1));
1262 tlb
= &env
->tlb
.tlb6
[entry
];
1263 cpu_fprintf(f
, "%s TLB %02d/%02d way:%d %s ["
1264 TARGET_FMT_lx
" " TARGET_FMT_lx
"]\n",
1265 type
? "code" : "data", entry
% env
->nb_tlb
,
1267 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
1268 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
);
1274 void dump_mmu(FILE *f
, fprintf_function cpu_fprintf
, CPUPPCState
*env
)
1276 switch (env
->mmu_model
) {
1277 case POWERPC_MMU_BOOKE
:
1278 mmubooke_dump_mmu(f
, cpu_fprintf
, env
);
1280 case POWERPC_MMU_BOOKE206
:
1281 mmubooke206_dump_mmu(f
, cpu_fprintf
, env
);
1283 case POWERPC_MMU_SOFT_6xx
:
1284 case POWERPC_MMU_SOFT_74xx
:
1285 mmu6xx_dump_mmu(f
, cpu_fprintf
, env
);
1287 #if defined(TARGET_PPC64)
1288 case POWERPC_MMU_64B
:
1289 case POWERPC_MMU_2_06
:
1290 case POWERPC_MMU_2_06a
:
1291 case POWERPC_MMU_2_06d
:
1292 dump_slb(f
, cpu_fprintf
, env
);
1296 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented\n", __func__
);
1300 static inline int check_physical(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1301 target_ulong eaddr
, int rw
)
1306 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1308 switch (env
->mmu_model
) {
1309 case POWERPC_MMU_SOFT_6xx
:
1310 case POWERPC_MMU_SOFT_74xx
:
1311 case POWERPC_MMU_SOFT_4xx
:
1312 case POWERPC_MMU_REAL
:
1313 case POWERPC_MMU_BOOKE
:
1314 ctx
->prot
|= PAGE_WRITE
;
1317 case POWERPC_MMU_SOFT_4xx_Z
:
1318 if (unlikely(msr_pe
!= 0)) {
1319 /* 403 family add some particular protections,
1320 * using PBL/PBU registers for accesses with no translation.
1323 /* Check PLB validity */
1324 (env
->pb
[0] < env
->pb
[1] &&
1325 /* and address in plb area */
1326 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1327 (env
->pb
[2] < env
->pb
[3] &&
1328 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1329 if (in_plb
^ msr_px
) {
1330 /* Access in protected area */
1332 /* Access is not allowed */
1336 /* Read-write access is allowed */
1337 ctx
->prot
|= PAGE_WRITE
;
1343 /* Caller's checks mean we should never get here for other models */
1351 static int get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1352 target_ulong eaddr
, int rw
, int access_type
)
1354 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1356 bool real_mode
= (access_type
== ACCESS_CODE
&& msr_ir
== 0)
1357 || (access_type
!= ACCESS_CODE
&& msr_dr
== 0);
1360 qemu_log("%s\n", __func__
);
1363 switch (env
->mmu_model
) {
1364 case POWERPC_MMU_SOFT_6xx
:
1365 case POWERPC_MMU_SOFT_74xx
:
1367 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1369 /* Try to find a BAT */
1370 if (env
->nb_BATs
!= 0) {
1371 ret
= get_bat_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1374 /* We didn't match any BAT entry or don't have BATs */
1375 ret
= get_segment_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1380 case POWERPC_MMU_SOFT_4xx
:
1381 case POWERPC_MMU_SOFT_4xx_Z
:
1383 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1385 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1389 case POWERPC_MMU_BOOKE
:
1390 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1393 case POWERPC_MMU_BOOKE206
:
1394 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1397 case POWERPC_MMU_MPC8xx
:
1399 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1401 case POWERPC_MMU_REAL
:
1403 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1405 cpu_abort(CPU(cpu
), "PowerPC in real mode do not do any translation\n");
1409 cpu_abort(CPU(cpu
), "Unknown or invalid MMU model\n");
1413 qemu_log("%s address " TARGET_FMT_lx
" => %d " TARGET_FMT_plx
"\n",
1414 __func__
, eaddr
, ret
, ctx
->raddr
);
1420 hwaddr
ppc_cpu_get_phys_page_debug(CPUState
*cs
, vaddr addr
)
1422 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
1423 CPUPPCState
*env
= &cpu
->env
;
1426 switch (env
->mmu_model
) {
1427 #if defined(TARGET_PPC64)
1428 case POWERPC_MMU_64B
:
1429 case POWERPC_MMU_2_06
:
1430 case POWERPC_MMU_2_06a
:
1431 case POWERPC_MMU_2_06d
:
1432 return ppc_hash64_get_phys_page_debug(env
, addr
);
1435 case POWERPC_MMU_32B
:
1436 case POWERPC_MMU_601
:
1437 return ppc_hash32_get_phys_page_debug(env
, addr
);
1443 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0)) {
1445 /* Some MMUs have separate TLBs for code and data. If we only try an
1446 * ACCESS_INT, we may not be able to read instructions mapped by code
1447 * TLBs, so we also try a ACCESS_CODE.
1449 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0,
1450 ACCESS_CODE
) != 0)) {
1455 return ctx
.raddr
& TARGET_PAGE_MASK
;
1458 static void booke206_update_mas_tlb_miss(CPUPPCState
*env
, target_ulong address
,
1461 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
1462 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
1463 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
1464 env
->spr
[SPR_BOOKE_MAS3
] = 0;
1465 env
->spr
[SPR_BOOKE_MAS6
] = 0;
1466 env
->spr
[SPR_BOOKE_MAS7
] = 0;
1469 if (((rw
== 2) && msr_ir
) || ((rw
!= 2) && msr_dr
)) {
1470 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
1471 env
->spr
[SPR_BOOKE_MAS6
] |= MAS6_SAS
;
1474 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_VALID
;
1475 env
->spr
[SPR_BOOKE_MAS2
] |= address
& MAS2_EPN_MASK
;
1477 switch (env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TIDSELD_PIDZ
) {
1478 case MAS4_TIDSELD_PID0
:
1479 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID
] << MAS1_TID_SHIFT
;
1481 case MAS4_TIDSELD_PID1
:
1482 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID1
] << MAS1_TID_SHIFT
;
1484 case MAS4_TIDSELD_PID2
:
1485 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID2
] << MAS1_TID_SHIFT
;
1489 env
->spr
[SPR_BOOKE_MAS6
] |= env
->spr
[SPR_BOOKE_PID
] << 16;
1491 /* next victim logic */
1492 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
1494 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
1495 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
1498 /* Perform address translation */
1499 static int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
,
1500 int rw
, int mmu_idx
)
1502 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1510 access_type
= ACCESS_CODE
;
1513 access_type
= env
->access_type
;
1515 ret
= get_physical_address(env
, &ctx
, address
, rw
, access_type
);
1517 tlb_set_page(cs
, address
& TARGET_PAGE_MASK
,
1518 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1519 mmu_idx
, TARGET_PAGE_SIZE
);
1521 } else if (ret
< 0) {
1523 if (access_type
== ACCESS_CODE
) {
1526 /* No matches in page tables or TLB */
1527 switch (env
->mmu_model
) {
1528 case POWERPC_MMU_SOFT_6xx
:
1529 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1530 env
->error_code
= 1 << 18;
1531 env
->spr
[SPR_IMISS
] = address
;
1532 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1534 case POWERPC_MMU_SOFT_74xx
:
1535 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1537 case POWERPC_MMU_SOFT_4xx
:
1538 case POWERPC_MMU_SOFT_4xx_Z
:
1539 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1540 env
->error_code
= 0;
1541 env
->spr
[SPR_40x_DEAR
] = address
;
1542 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1544 case POWERPC_MMU_BOOKE206
:
1545 booke206_update_mas_tlb_miss(env
, address
, rw
);
1547 case POWERPC_MMU_BOOKE
:
1548 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1549 env
->error_code
= 0;
1550 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1552 case POWERPC_MMU_MPC8xx
:
1554 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1556 case POWERPC_MMU_REAL
:
1557 cpu_abort(cs
, "PowerPC in real mode should never raise "
1558 "any MMU exceptions\n");
1561 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1566 /* Access rights violation */
1567 cs
->exception_index
= POWERPC_EXCP_ISI
;
1568 env
->error_code
= 0x08000000;
1571 /* No execute protection violation */
1572 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1573 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1574 env
->spr
[SPR_BOOKE_ESR
] = 0x00000000;
1576 cs
->exception_index
= POWERPC_EXCP_ISI
;
1577 env
->error_code
= 0x10000000;
1580 /* Direct store exception */
1581 /* No code fetch is allowed in direct-store areas */
1582 cs
->exception_index
= POWERPC_EXCP_ISI
;
1583 env
->error_code
= 0x10000000;
1589 /* No matches in page tables or TLB */
1590 switch (env
->mmu_model
) {
1591 case POWERPC_MMU_SOFT_6xx
:
1593 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1594 env
->error_code
= 1 << 16;
1596 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1597 env
->error_code
= 0;
1599 env
->spr
[SPR_DMISS
] = address
;
1600 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1602 env
->error_code
|= ctx
.key
<< 19;
1603 env
->spr
[SPR_HASH1
] = env
->htab_base
+
1604 get_pteg_offset32(env
, ctx
.hash
[0]);
1605 env
->spr
[SPR_HASH2
] = env
->htab_base
+
1606 get_pteg_offset32(env
, ctx
.hash
[1]);
1608 case POWERPC_MMU_SOFT_74xx
:
1610 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1612 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1615 /* Implement LRU algorithm */
1616 env
->error_code
= ctx
.key
<< 19;
1617 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1618 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1619 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1621 case POWERPC_MMU_SOFT_4xx
:
1622 case POWERPC_MMU_SOFT_4xx_Z
:
1623 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1624 env
->error_code
= 0;
1625 env
->spr
[SPR_40x_DEAR
] = address
;
1627 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1629 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1632 case POWERPC_MMU_MPC8xx
:
1634 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1636 case POWERPC_MMU_BOOKE206
:
1637 booke206_update_mas_tlb_miss(env
, address
, rw
);
1639 case POWERPC_MMU_BOOKE
:
1640 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1641 env
->error_code
= 0;
1642 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1643 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1645 case POWERPC_MMU_REAL
:
1646 cpu_abort(cs
, "PowerPC in real mode should never raise "
1647 "any MMU exceptions\n");
1650 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1655 /* Access rights violation */
1656 cs
->exception_index
= POWERPC_EXCP_DSI
;
1657 env
->error_code
= 0;
1658 if (env
->mmu_model
== POWERPC_MMU_SOFT_4xx
1659 || env
->mmu_model
== POWERPC_MMU_SOFT_4xx_Z
) {
1660 env
->spr
[SPR_40x_DEAR
] = address
;
1662 env
->spr
[SPR_40x_ESR
] |= 0x00800000;
1664 } else if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1665 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1666 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1667 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1669 env
->spr
[SPR_DAR
] = address
;
1671 env
->spr
[SPR_DSISR
] = 0x0A000000;
1673 env
->spr
[SPR_DSISR
] = 0x08000000;
1678 /* Direct store exception */
1679 switch (access_type
) {
1681 /* Floating point load/store */
1682 cs
->exception_index
= POWERPC_EXCP_ALIGN
;
1683 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1684 env
->spr
[SPR_DAR
] = address
;
1687 /* lwarx, ldarx or stwcx. */
1688 cs
->exception_index
= POWERPC_EXCP_DSI
;
1689 env
->error_code
= 0;
1690 env
->spr
[SPR_DAR
] = address
;
1692 env
->spr
[SPR_DSISR
] = 0x06000000;
1694 env
->spr
[SPR_DSISR
] = 0x04000000;
1698 /* eciwx or ecowx */
1699 cs
->exception_index
= POWERPC_EXCP_DSI
;
1700 env
->error_code
= 0;
1701 env
->spr
[SPR_DAR
] = address
;
1703 env
->spr
[SPR_DSISR
] = 0x06100000;
1705 env
->spr
[SPR_DSISR
] = 0x04100000;
1709 printf("DSI: invalid exception (%d)\n", ret
);
1710 cs
->exception_index
= POWERPC_EXCP_PROGRAM
;
1712 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1713 env
->spr
[SPR_DAR
] = address
;
1720 printf("%s: set exception to %d %02x\n", __func__
,
1721 cs
->exception
, env
->error_code
);
1729 /*****************************************************************************/
1730 /* BATs management */
1731 #if !defined(FLUSH_ALL_TLBS)
1732 static inline void do_invalidate_BAT(CPUPPCState
*env
, target_ulong BATu
,
1735 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1736 target_ulong base
, end
, page
;
1738 base
= BATu
& ~0x0001FFFF;
1739 end
= base
+ mask
+ 0x00020000;
1740 LOG_BATS("Flush BAT from " TARGET_FMT_lx
" to " TARGET_FMT_lx
" ("
1741 TARGET_FMT_lx
")\n", base
, end
, mask
);
1742 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
1743 tlb_flush_page(cs
, page
);
1745 LOG_BATS("Flush done\n");
1749 static inline void dump_store_bat(CPUPPCState
*env
, char ID
, int ul
, int nr
,
1752 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx
" (" TARGET_FMT_lx
")\n", ID
,
1753 nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1756 void helper_store_ibatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1760 dump_store_bat(env
, 'I', 0, nr
, value
);
1761 if (env
->IBAT
[0][nr
] != value
) {
1762 mask
= (value
<< 15) & 0x0FFE0000UL
;
1763 #if !defined(FLUSH_ALL_TLBS)
1764 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1766 /* When storing valid upper BAT, mask BEPI and BRPN
1767 * and invalidate all TLBs covered by this BAT
1769 mask
= (value
<< 15) & 0x0FFE0000UL
;
1770 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1771 (value
& ~0x0001FFFFUL
& ~mask
);
1772 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1773 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1774 #if !defined(FLUSH_ALL_TLBS)
1775 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1782 void helper_store_ibatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1784 dump_store_bat(env
, 'I', 1, nr
, value
);
1785 env
->IBAT
[1][nr
] = value
;
1788 void helper_store_dbatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1792 dump_store_bat(env
, 'D', 0, nr
, value
);
1793 if (env
->DBAT
[0][nr
] != value
) {
1794 /* When storing valid upper BAT, mask BEPI and BRPN
1795 * and invalidate all TLBs covered by this BAT
1797 mask
= (value
<< 15) & 0x0FFE0000UL
;
1798 #if !defined(FLUSH_ALL_TLBS)
1799 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1801 mask
= (value
<< 15) & 0x0FFE0000UL
;
1802 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1803 (value
& ~0x0001FFFFUL
& ~mask
);
1804 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1805 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1806 #if !defined(FLUSH_ALL_TLBS)
1807 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1814 void helper_store_dbatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1816 dump_store_bat(env
, 'D', 1, nr
, value
);
1817 env
->DBAT
[1][nr
] = value
;
1820 void helper_store_601_batu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1823 #if defined(FLUSH_ALL_TLBS)
1827 dump_store_bat(env
, 'I', 0, nr
, value
);
1828 if (env
->IBAT
[0][nr
] != value
) {
1829 #if defined(FLUSH_ALL_TLBS)
1832 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1833 if (env
->IBAT
[1][nr
] & 0x40) {
1834 /* Invalidate BAT only if it is valid */
1835 #if !defined(FLUSH_ALL_TLBS)
1836 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1841 /* When storing valid upper BAT, mask BEPI and BRPN
1842 * and invalidate all TLBs covered by this BAT
1844 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1845 (value
& ~0x0001FFFFUL
& ~mask
);
1846 env
->DBAT
[0][nr
] = env
->IBAT
[0][nr
];
1847 if (env
->IBAT
[1][nr
] & 0x40) {
1848 #if !defined(FLUSH_ALL_TLBS)
1849 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1854 #if defined(FLUSH_ALL_TLBS)
1862 void helper_store_601_batl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1864 #if !defined(FLUSH_ALL_TLBS)
1870 dump_store_bat(env
, 'I', 1, nr
, value
);
1871 if (env
->IBAT
[1][nr
] != value
) {
1872 #if defined(FLUSH_ALL_TLBS)
1875 if (env
->IBAT
[1][nr
] & 0x40) {
1876 #if !defined(FLUSH_ALL_TLBS)
1877 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1878 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1884 #if !defined(FLUSH_ALL_TLBS)
1885 mask
= (value
<< 17) & 0x0FFE0000UL
;
1886 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1891 env
->IBAT
[1][nr
] = value
;
1892 env
->DBAT
[1][nr
] = value
;
1893 #if defined(FLUSH_ALL_TLBS)
1901 /*****************************************************************************/
1902 /* TLB management */
1903 void ppc_tlb_invalidate_all(CPUPPCState
*env
)
1905 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1907 switch (env
->mmu_model
) {
1908 case POWERPC_MMU_SOFT_6xx
:
1909 case POWERPC_MMU_SOFT_74xx
:
1910 ppc6xx_tlb_invalidate_all(env
);
1912 case POWERPC_MMU_SOFT_4xx
:
1913 case POWERPC_MMU_SOFT_4xx_Z
:
1914 ppc4xx_tlb_invalidate_all(env
);
1916 case POWERPC_MMU_REAL
:
1917 cpu_abort(CPU(cpu
), "No TLB for PowerPC 4xx in real mode\n");
1919 case POWERPC_MMU_MPC8xx
:
1921 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1923 case POWERPC_MMU_BOOKE
:
1924 tlb_flush(CPU(cpu
), 1);
1926 case POWERPC_MMU_BOOKE206
:
1927 booke206_flush_tlb(env
, -1, 0);
1929 case POWERPC_MMU_32B
:
1930 case POWERPC_MMU_601
:
1931 #if defined(TARGET_PPC64)
1932 case POWERPC_MMU_64B
:
1933 case POWERPC_MMU_2_06
:
1934 case POWERPC_MMU_2_06a
:
1935 case POWERPC_MMU_2_06d
:
1936 #endif /* defined(TARGET_PPC64) */
1937 tlb_flush(CPU(cpu
), 1);
1941 cpu_abort(CPU(cpu
), "Unknown MMU model\n");
1946 void ppc_tlb_invalidate_one(CPUPPCState
*env
, target_ulong addr
)
1948 #if !defined(FLUSH_ALL_TLBS)
1949 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1952 addr
&= TARGET_PAGE_MASK
;
1953 switch (env
->mmu_model
) {
1954 case POWERPC_MMU_SOFT_6xx
:
1955 case POWERPC_MMU_SOFT_74xx
:
1956 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
1957 if (env
->id_tlbs
== 1) {
1958 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
1961 case POWERPC_MMU_SOFT_4xx
:
1962 case POWERPC_MMU_SOFT_4xx_Z
:
1963 ppc4xx_tlb_invalidate_virt(env
, addr
, env
->spr
[SPR_40x_PID
]);
1965 case POWERPC_MMU_REAL
:
1966 cpu_abort(CPU(cpu
), "No TLB for PowerPC 4xx in real mode\n");
1968 case POWERPC_MMU_MPC8xx
:
1970 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1972 case POWERPC_MMU_BOOKE
:
1974 cpu_abort(CPU(cpu
), "BookE MMU model is not implemented\n");
1976 case POWERPC_MMU_BOOKE206
:
1978 cpu_abort(CPU(cpu
), "BookE 2.06 MMU model is not implemented\n");
1980 case POWERPC_MMU_32B
:
1981 case POWERPC_MMU_601
:
1982 /* tlbie invalidate TLBs for all segments */
1983 addr
&= ~((target_ulong
)-1ULL << 28);
1985 /* XXX: this case should be optimized,
1986 * giving a mask to tlb_flush_page
1988 tlb_flush_page(cs
, addr
| (0x0 << 28));
1989 tlb_flush_page(cs
, addr
| (0x1 << 28));
1990 tlb_flush_page(cs
, addr
| (0x2 << 28));
1991 tlb_flush_page(cs
, addr
| (0x3 << 28));
1992 tlb_flush_page(cs
, addr
| (0x4 << 28));
1993 tlb_flush_page(cs
, addr
| (0x5 << 28));
1994 tlb_flush_page(cs
, addr
| (0x6 << 28));
1995 tlb_flush_page(cs
, addr
| (0x7 << 28));
1996 tlb_flush_page(cs
, addr
| (0x8 << 28));
1997 tlb_flush_page(cs
, addr
| (0x9 << 28));
1998 tlb_flush_page(cs
, addr
| (0xA << 28));
1999 tlb_flush_page(cs
, addr
| (0xB << 28));
2000 tlb_flush_page(cs
, addr
| (0xC << 28));
2001 tlb_flush_page(cs
, addr
| (0xD << 28));
2002 tlb_flush_page(cs
, addr
| (0xE << 28));
2003 tlb_flush_page(cs
, addr
| (0xF << 28));
2005 #if defined(TARGET_PPC64)
2006 case POWERPC_MMU_64B
:
2007 case POWERPC_MMU_2_06
:
2008 case POWERPC_MMU_2_06a
:
2009 case POWERPC_MMU_2_06d
:
2010 /* tlbie invalidate TLBs for all segments */
2011 /* XXX: given the fact that there are too many segments to invalidate,
2012 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
2013 * we just invalidate all TLBs
2015 tlb_flush(CPU(cpu
), 1);
2017 #endif /* defined(TARGET_PPC64) */
2020 cpu_abort(CPU(cpu
), "Unknown MMU model\n");
2024 ppc_tlb_invalidate_all(env
);
2028 /*****************************************************************************/
2029 /* Special registers manipulation */
2030 void ppc_store_sdr1(CPUPPCState
*env
, target_ulong value
)
2032 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2034 LOG_MMU("%s: " TARGET_FMT_lx
"\n", __func__
, value
);
2035 assert(!env
->external_htab
);
2036 if (env
->spr
[SPR_SDR1
] != value
) {
2037 env
->spr
[SPR_SDR1
] = value
;
2038 #if defined(TARGET_PPC64)
2039 if (env
->mmu_model
& POWERPC_MMU_64
) {
2040 target_ulong htabsize
= value
& SDR_64_HTABSIZE
;
2042 if (htabsize
> 28) {
2043 fprintf(stderr
, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2044 " stored in SDR1\n", htabsize
);
2047 env
->htab_mask
= (1ULL << (htabsize
+ 18 - 7)) - 1;
2048 env
->htab_base
= value
& SDR_64_HTABORG
;
2050 #endif /* defined(TARGET_PPC64) */
2052 /* FIXME: Should check for valid HTABMASK values */
2053 env
->htab_mask
= ((value
& SDR_32_HTABMASK
) << 16) | 0xFFFF;
2054 env
->htab_base
= value
& SDR_32_HTABORG
;
2056 tlb_flush(CPU(cpu
), 1);
2060 /* Segment registers load and store */
2061 target_ulong
helper_load_sr(CPUPPCState
*env
, target_ulong sr_num
)
2063 #if defined(TARGET_PPC64)
2064 if (env
->mmu_model
& POWERPC_MMU_64
) {
2069 return env
->sr
[sr_num
];
2072 void helper_store_sr(CPUPPCState
*env
, target_ulong srnum
, target_ulong value
)
2074 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2076 LOG_MMU("%s: reg=%d " TARGET_FMT_lx
" " TARGET_FMT_lx
"\n", __func__
,
2077 (int)srnum
, value
, env
->sr
[srnum
]);
2078 #if defined(TARGET_PPC64)
2079 if (env
->mmu_model
& POWERPC_MMU_64
) {
2080 uint64_t rb
= 0, rs
= 0;
2083 rb
|= ((uint32_t)srnum
& 0xf) << 28;
2084 /* Set the valid bit */
2087 rb
|= (uint32_t)srnum
;
2090 rs
|= (value
& 0xfffffff) << 12;
2092 rs
|= ((value
>> 27) & 0xf) << 8;
2094 ppc_store_slb(env
, rb
, rs
);
2097 if (env
->sr
[srnum
] != value
) {
2098 env
->sr
[srnum
] = value
;
2099 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2100 flusing the whole TLB. */
2101 #if !defined(FLUSH_ALL_TLBS) && 0
2103 target_ulong page
, end
;
2104 /* Invalidate 256 MB of virtual memory */
2105 page
= (16 << 20) * srnum
;
2106 end
= page
+ (16 << 20);
2107 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
2108 tlb_flush_page(CPU(cpu
), page
);
2112 tlb_flush(CPU(cpu
), 1);
2117 /* TLB management */
2118 void helper_tlbia(CPUPPCState
*env
)
2120 ppc_tlb_invalidate_all(env
);
2123 void helper_tlbie(CPUPPCState
*env
, target_ulong addr
)
2125 ppc_tlb_invalidate_one(env
, addr
);
2128 /* Software driven TLBs management */
2129 /* PowerPC 602/603 software TLB load instructions helpers */
2130 static void do_6xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2132 target_ulong RPN
, CMP
, EPN
;
2135 RPN
= env
->spr
[SPR_RPA
];
2137 CMP
= env
->spr
[SPR_ICMP
];
2138 EPN
= env
->spr
[SPR_IMISS
];
2140 CMP
= env
->spr
[SPR_DCMP
];
2141 EPN
= env
->spr
[SPR_DMISS
];
2143 way
= (env
->spr
[SPR_SRR1
] >> 17) & 1;
2144 (void)EPN
; /* avoid a compiler warning */
2145 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2146 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2148 /* Store this TLB */
2149 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2150 way
, is_code
, CMP
, RPN
);
2153 void helper_6xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2155 do_6xx_tlb(env
, EPN
, 0);
2158 void helper_6xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2160 do_6xx_tlb(env
, EPN
, 1);
2163 /* PowerPC 74xx software TLB load instructions helpers */
2164 static void do_74xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2166 target_ulong RPN
, CMP
, EPN
;
2169 RPN
= env
->spr
[SPR_PTELO
];
2170 CMP
= env
->spr
[SPR_PTEHI
];
2171 EPN
= env
->spr
[SPR_TLBMISS
] & ~0x3;
2172 way
= env
->spr
[SPR_TLBMISS
] & 0x3;
2173 (void)EPN
; /* avoid a compiler warning */
2174 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2175 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2177 /* Store this TLB */
2178 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2179 way
, is_code
, CMP
, RPN
);
2182 void helper_74xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2184 do_74xx_tlb(env
, EPN
, 0);
2187 void helper_74xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2189 do_74xx_tlb(env
, EPN
, 1);
2192 /*****************************************************************************/
2193 /* PowerPC 601 specific instructions (POWER bridge) */
2195 target_ulong
helper_rac(CPUPPCState
*env
, target_ulong addr
)
2199 target_ulong ret
= 0;
2201 /* We don't have to generate many instances of this instruction,
2202 * as rac is supervisor only.
2204 /* XXX: FIX THIS: Pretend we have no BAT */
2205 nb_BATs
= env
->nb_BATs
;
2207 if (get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) == 0) {
2210 env
->nb_BATs
= nb_BATs
;
2214 static inline target_ulong
booke_tlb_to_page_size(int size
)
2216 return 1024 << (2 * size
);
2219 static inline int booke_page_size_to_tlb(target_ulong page_size
)
2223 switch (page_size
) {
2257 #if defined(TARGET_PPC64)
2258 case 0x000100000000ULL
:
2261 case 0x000400000000ULL
:
2264 case 0x001000000000ULL
:
2267 case 0x004000000000ULL
:
2270 case 0x010000000000ULL
:
2282 /* Helpers for 4xx TLB management */
2283 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2285 #define PPC4XX_TLBHI_V 0x00000040
2286 #define PPC4XX_TLBHI_E 0x00000020
2287 #define PPC4XX_TLBHI_SIZE_MIN 0
2288 #define PPC4XX_TLBHI_SIZE_MAX 7
2289 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2290 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2291 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2293 #define PPC4XX_TLBLO_EX 0x00000200
2294 #define PPC4XX_TLBLO_WR 0x00000100
2295 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2296 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2298 target_ulong
helper_4xx_tlbre_hi(CPUPPCState
*env
, target_ulong entry
)
2304 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2305 tlb
= &env
->tlb
.tlbe
[entry
];
2307 if (tlb
->prot
& PAGE_VALID
) {
2308 ret
|= PPC4XX_TLBHI_V
;
2310 size
= booke_page_size_to_tlb(tlb
->size
);
2311 if (size
< PPC4XX_TLBHI_SIZE_MIN
|| size
> PPC4XX_TLBHI_SIZE_MAX
) {
2312 size
= PPC4XX_TLBHI_SIZE_DEFAULT
;
2314 ret
|= size
<< PPC4XX_TLBHI_SIZE_SHIFT
;
2315 env
->spr
[SPR_40x_PID
] = tlb
->PID
;
2319 target_ulong
helper_4xx_tlbre_lo(CPUPPCState
*env
, target_ulong entry
)
2324 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2325 tlb
= &env
->tlb
.tlbe
[entry
];
2327 if (tlb
->prot
& PAGE_EXEC
) {
2328 ret
|= PPC4XX_TLBLO_EX
;
2330 if (tlb
->prot
& PAGE_WRITE
) {
2331 ret
|= PPC4XX_TLBLO_WR
;
2336 void helper_4xx_tlbwe_hi(CPUPPCState
*env
, target_ulong entry
,
2339 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2340 CPUState
*cs
= CPU(cpu
);
2342 target_ulong page
, end
;
2344 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2346 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2347 tlb
= &env
->tlb
.tlbe
[entry
];
2348 /* Invalidate previous TLB (if it's valid) */
2349 if (tlb
->prot
& PAGE_VALID
) {
2350 end
= tlb
->EPN
+ tlb
->size
;
2351 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx
" end "
2352 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2353 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2354 tlb_flush_page(cs
, page
);
2357 tlb
->size
= booke_tlb_to_page_size((val
>> PPC4XX_TLBHI_SIZE_SHIFT
)
2358 & PPC4XX_TLBHI_SIZE_MASK
);
2359 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2360 * If this ever occurs, one should use the ppcemb target instead
2361 * of the ppc or ppc64 one
2363 if ((val
& PPC4XX_TLBHI_V
) && tlb
->size
< TARGET_PAGE_SIZE
) {
2364 cpu_abort(cs
, "TLB size " TARGET_FMT_lu
" < %u "
2365 "are not supported (%d)\n",
2366 tlb
->size
, TARGET_PAGE_SIZE
, (int)((val
>> 7) & 0x7));
2368 tlb
->EPN
= val
& ~(tlb
->size
- 1);
2369 if (val
& PPC4XX_TLBHI_V
) {
2370 tlb
->prot
|= PAGE_VALID
;
2371 if (val
& PPC4XX_TLBHI_E
) {
2372 /* XXX: TO BE FIXED */
2374 "Little-endian TLB entries are not supported by now\n");
2377 tlb
->prot
&= ~PAGE_VALID
;
2379 tlb
->PID
= env
->spr
[SPR_40x_PID
]; /* PID */
2380 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2381 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2382 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2383 tlb
->prot
& PAGE_READ
? 'r' : '-',
2384 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2385 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2386 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2387 /* Invalidate new TLB (if valid) */
2388 if (tlb
->prot
& PAGE_VALID
) {
2389 end
= tlb
->EPN
+ tlb
->size
;
2390 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx
" end "
2391 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2392 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2393 tlb_flush_page(cs
, page
);
2398 void helper_4xx_tlbwe_lo(CPUPPCState
*env
, target_ulong entry
,
2403 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2405 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2406 tlb
= &env
->tlb
.tlbe
[entry
];
2407 tlb
->attr
= val
& PPC4XX_TLBLO_ATTR_MASK
;
2408 tlb
->RPN
= val
& PPC4XX_TLBLO_RPN_MASK
;
2409 tlb
->prot
= PAGE_READ
;
2410 if (val
& PPC4XX_TLBLO_EX
) {
2411 tlb
->prot
|= PAGE_EXEC
;
2413 if (val
& PPC4XX_TLBLO_WR
) {
2414 tlb
->prot
|= PAGE_WRITE
;
2416 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2417 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2418 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2419 tlb
->prot
& PAGE_READ
? 'r' : '-',
2420 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2421 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2422 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2425 target_ulong
helper_4xx_tlbsx(CPUPPCState
*env
, target_ulong address
)
2427 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_40x_PID
]);
2430 /* PowerPC 440 TLB management */
2431 void helper_440_tlbwe(CPUPPCState
*env
, uint32_t word
, target_ulong entry
,
2434 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2436 target_ulong EPN
, RPN
, size
;
2439 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx
"\n",
2440 __func__
, word
, (int)entry
, value
);
2443 tlb
= &env
->tlb
.tlbe
[entry
];
2446 /* Just here to please gcc */
2448 EPN
= value
& 0xFFFFFC00;
2449 if ((tlb
->prot
& PAGE_VALID
) && EPN
!= tlb
->EPN
) {
2453 size
= booke_tlb_to_page_size((value
>> 4) & 0xF);
2454 if ((tlb
->prot
& PAGE_VALID
) && tlb
->size
< size
) {
2459 tlb
->attr
|= (value
>> 8) & 1;
2460 if (value
& 0x200) {
2461 tlb
->prot
|= PAGE_VALID
;
2463 if (tlb
->prot
& PAGE_VALID
) {
2464 tlb
->prot
&= ~PAGE_VALID
;
2468 tlb
->PID
= env
->spr
[SPR_440_MMUCR
] & 0x000000FF;
2469 if (do_flush_tlbs
) {
2470 tlb_flush(CPU(cpu
), 1);
2474 RPN
= value
& 0xFFFFFC0F;
2475 if ((tlb
->prot
& PAGE_VALID
) && tlb
->RPN
!= RPN
) {
2476 tlb_flush(CPU(cpu
), 1);
2481 tlb
->attr
= (tlb
->attr
& 0x1) | (value
& 0x0000FF00);
2482 tlb
->prot
= tlb
->prot
& PAGE_VALID
;
2484 tlb
->prot
|= PAGE_READ
<< 4;
2487 tlb
->prot
|= PAGE_WRITE
<< 4;
2490 tlb
->prot
|= PAGE_EXEC
<< 4;
2493 tlb
->prot
|= PAGE_READ
;
2496 tlb
->prot
|= PAGE_WRITE
;
2499 tlb
->prot
|= PAGE_EXEC
;
2505 target_ulong
helper_440_tlbre(CPUPPCState
*env
, uint32_t word
,
2513 tlb
= &env
->tlb
.tlbe
[entry
];
2516 /* Just here to please gcc */
2519 size
= booke_page_size_to_tlb(tlb
->size
);
2520 if (size
< 0 || size
> 0xF) {
2524 if (tlb
->attr
& 0x1) {
2527 if (tlb
->prot
& PAGE_VALID
) {
2530 env
->spr
[SPR_440_MMUCR
] &= ~0x000000FF;
2531 env
->spr
[SPR_440_MMUCR
] |= tlb
->PID
;
2537 ret
= tlb
->attr
& ~0x1;
2538 if (tlb
->prot
& (PAGE_READ
<< 4)) {
2541 if (tlb
->prot
& (PAGE_WRITE
<< 4)) {
2544 if (tlb
->prot
& (PAGE_EXEC
<< 4)) {
2547 if (tlb
->prot
& PAGE_READ
) {
2550 if (tlb
->prot
& PAGE_WRITE
) {
2553 if (tlb
->prot
& PAGE_EXEC
) {
2561 target_ulong
helper_440_tlbsx(CPUPPCState
*env
, target_ulong address
)
2563 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_440_MMUCR
] & 0xFF);
2566 /* PowerPC BookE 2.06 TLB management */
2568 static ppcmas_tlb_t
*booke206_cur_tlb(CPUPPCState
*env
)
2570 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2571 uint32_t tlbncfg
= 0;
2572 int esel
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ESEL_MASK
) >> MAS0_ESEL_SHIFT
;
2573 int ea
= (env
->spr
[SPR_BOOKE_MAS2
] & MAS2_EPN_MASK
);
2576 tlb
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2577 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlb
];
2579 if ((tlbncfg
& TLBnCFG_HES
) && (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_HES
)) {
2580 cpu_abort(CPU(cpu
), "we don't support HES yet\n");
2583 return booke206_get_tlbm(env
, tlb
, ea
, esel
);
2586 void helper_booke_setpid(CPUPPCState
*env
, uint32_t pidn
, target_ulong pid
)
2588 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2590 env
->spr
[pidn
] = pid
;
2591 /* changing PIDs mean we're in a different address space now */
2592 tlb_flush(CPU(cpu
), 1);
2595 void helper_booke206_tlbwe(CPUPPCState
*env
)
2597 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2598 uint32_t tlbncfg
, tlbn
;
2600 uint32_t size_tlb
, size_ps
;
2604 switch (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_WQ_MASK
) {
2605 case MAS0_WQ_ALWAYS
:
2606 /* good to go, write that entry */
2609 /* XXX check if reserved */
2614 case MAS0_WQ_CLR_RSRV
:
2615 /* XXX clear entry */
2618 /* no idea what to do */
2622 if (((env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ATSEL
) == MAS0_ATSEL_LRAT
) &&
2624 /* XXX we don't support direct LRAT setting yet */
2625 fprintf(stderr
, "cpu: don't support LRAT setting yet\n");
2629 tlbn
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2630 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlbn
];
2632 tlb
= booke206_cur_tlb(env
);
2635 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2636 POWERPC_EXCP_INVAL
|
2637 POWERPC_EXCP_INVAL_INVAL
);
2640 /* check that we support the targeted size */
2641 size_tlb
= (env
->spr
[SPR_BOOKE_MAS1
] & MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
2642 size_ps
= booke206_tlbnps(env
, tlbn
);
2643 if ((env
->spr
[SPR_BOOKE_MAS1
] & MAS1_VALID
) && (tlbncfg
& TLBnCFG_AVAIL
) &&
2644 !(size_ps
& (1 << size_tlb
))) {
2645 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2646 POWERPC_EXCP_INVAL
|
2647 POWERPC_EXCP_INVAL_INVAL
);
2651 cpu_abort(CPU(cpu
), "missing HV implementation\n");
2653 tlb
->mas7_3
= ((uint64_t)env
->spr
[SPR_BOOKE_MAS7
] << 32) |
2654 env
->spr
[SPR_BOOKE_MAS3
];
2655 tlb
->mas1
= env
->spr
[SPR_BOOKE_MAS1
];
2658 if (!(tlbncfg
& TLBnCFG_AVAIL
)) {
2659 /* force !AVAIL TLB entries to correct page size */
2660 tlb
->mas1
&= ~MAS1_TSIZE_MASK
;
2661 /* XXX can be configured in MMUCSR0 */
2662 tlb
->mas1
|= (tlbncfg
& TLBnCFG_MINSIZE
) >> 12;
2665 /* Make a mask from TLB size to discard invalid bits in EPN field */
2666 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2667 /* Add a mask for page attributes */
2668 mask
|= MAS2_ACM
| MAS2_VLE
| MAS2_W
| MAS2_I
| MAS2_M
| MAS2_G
| MAS2_E
;
2671 /* Executing a tlbwe instruction in 32-bit mode will set
2672 * bits 0:31 of the TLB EPN field to zero.
2677 tlb
->mas2
= env
->spr
[SPR_BOOKE_MAS2
] & mask
;
2679 if (!(tlbncfg
& TLBnCFG_IPROT
)) {
2680 /* no IPROT supported by TLB */
2681 tlb
->mas1
&= ~MAS1_IPROT
;
2684 if (booke206_tlb_to_page_size(env
, tlb
) == TARGET_PAGE_SIZE
) {
2685 tlb_flush_page(CPU(cpu
), tlb
->mas2
& MAS2_EPN_MASK
);
2687 tlb_flush(CPU(cpu
), 1);
2691 static inline void booke206_tlb_to_mas(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2693 int tlbn
= booke206_tlbm_to_tlbn(env
, tlb
);
2694 int way
= booke206_tlbm_to_way(env
, tlb
);
2696 env
->spr
[SPR_BOOKE_MAS0
] = tlbn
<< MAS0_TLBSEL_SHIFT
;
2697 env
->spr
[SPR_BOOKE_MAS0
] |= way
<< MAS0_ESEL_SHIFT
;
2698 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2700 env
->spr
[SPR_BOOKE_MAS1
] = tlb
->mas1
;
2701 env
->spr
[SPR_BOOKE_MAS2
] = tlb
->mas2
;
2702 env
->spr
[SPR_BOOKE_MAS3
] = tlb
->mas7_3
;
2703 env
->spr
[SPR_BOOKE_MAS7
] = tlb
->mas7_3
>> 32;
2706 void helper_booke206_tlbre(CPUPPCState
*env
)
2708 ppcmas_tlb_t
*tlb
= NULL
;
2710 tlb
= booke206_cur_tlb(env
);
2712 env
->spr
[SPR_BOOKE_MAS1
] = 0;
2714 booke206_tlb_to_mas(env
, tlb
);
2718 void helper_booke206_tlbsx(CPUPPCState
*env
, target_ulong address
)
2720 ppcmas_tlb_t
*tlb
= NULL
;
2725 spid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID_MASK
) >> MAS6_SPID_SHIFT
;
2726 sas
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
;
2728 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2729 int ways
= booke206_tlb_ways(env
, i
);
2731 for (j
= 0; j
< ways
; j
++) {
2732 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2738 if (ppcmas_tlb_check(env
, tlb
, &raddr
, address
, spid
)) {
2742 if (sas
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
2746 booke206_tlb_to_mas(env
, tlb
);
2751 /* no entry found, fill with defaults */
2752 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
2753 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
2754 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
2755 env
->spr
[SPR_BOOKE_MAS3
] = 0;
2756 env
->spr
[SPR_BOOKE_MAS7
] = 0;
2758 if (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
) {
2759 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
2762 env
->spr
[SPR_BOOKE_MAS1
] |= (env
->spr
[SPR_BOOKE_MAS6
] >> 16)
2765 /* next victim logic */
2766 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
2768 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
2769 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2772 static inline void booke206_invalidate_ea_tlb(CPUPPCState
*env
, int tlbn
,
2776 int ways
= booke206_tlb_ways(env
, tlbn
);
2779 for (i
= 0; i
< ways
; i
++) {
2780 ppcmas_tlb_t
*tlb
= booke206_get_tlbm(env
, tlbn
, ea
, i
);
2784 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2785 if (((tlb
->mas2
& MAS2_EPN_MASK
) == (ea
& mask
)) &&
2786 !(tlb
->mas1
& MAS1_IPROT
)) {
2787 tlb
->mas1
&= ~MAS1_VALID
;
2792 void helper_booke206_tlbivax(CPUPPCState
*env
, target_ulong address
)
2794 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2796 if (address
& 0x4) {
2797 /* flush all entries */
2798 if (address
& 0x8) {
2799 /* flush all of TLB1 */
2800 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB1
, 1);
2802 /* flush all of TLB0 */
2803 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB0
, 0);
2808 if (address
& 0x8) {
2809 /* flush TLB1 entries */
2810 booke206_invalidate_ea_tlb(env
, 1, address
);
2811 tlb_flush(CPU(cpu
), 1);
2813 /* flush TLB0 entries */
2814 booke206_invalidate_ea_tlb(env
, 0, address
);
2815 tlb_flush_page(CPU(cpu
), address
& MAS2_EPN_MASK
);
2819 void helper_booke206_tlbilx0(CPUPPCState
*env
, target_ulong address
)
2821 /* XXX missing LPID handling */
2822 booke206_flush_tlb(env
, -1, 1);
2825 void helper_booke206_tlbilx1(CPUPPCState
*env
, target_ulong address
)
2827 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2829 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2830 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
2833 /* XXX missing LPID handling */
2834 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2835 tlb_size
= booke206_tlb_size(env
, i
);
2836 for (j
= 0; j
< tlb_size
; j
++) {
2837 if (!(tlb
[j
].mas1
& MAS1_IPROT
) &&
2838 ((tlb
[j
].mas1
& MAS1_TID_MASK
) == tid
)) {
2839 tlb
[j
].mas1
&= ~MAS1_VALID
;
2842 tlb
+= booke206_tlb_size(env
, i
);
2844 tlb_flush(CPU(cpu
), 1);
2847 void helper_booke206_tlbilx3(CPUPPCState
*env
, target_ulong address
)
2849 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2852 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2853 int pid
= tid
>> MAS6_SPID_SHIFT
;
2854 int sgs
= env
->spr
[SPR_BOOKE_MAS5
] & MAS5_SGS
;
2855 int ind
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SIND
) ? MAS1_IND
: 0;
2856 /* XXX check for unsupported isize and raise an invalid opcode then */
2857 int size
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_ISIZE_MASK
;
2858 /* XXX implement MAV2 handling */
2861 /* XXX missing LPID handling */
2862 /* flush by pid and ea */
2863 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2864 int ways
= booke206_tlb_ways(env
, i
);
2866 for (j
= 0; j
< ways
; j
++) {
2867 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2871 if ((ppcmas_tlb_check(env
, tlb
, NULL
, address
, pid
) != 0) ||
2872 (tlb
->mas1
& MAS1_IPROT
) ||
2873 ((tlb
->mas1
& MAS1_IND
) != ind
) ||
2874 ((tlb
->mas8
& MAS8_TGS
) != sgs
)) {
2877 if (mav2
&& ((tlb
->mas1
& MAS1_TSIZE_MASK
) != size
)) {
2878 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2881 /* XXX e500mc doesn't match SAS, but other cores might */
2882 tlb
->mas1
&= ~MAS1_VALID
;
2885 tlb_flush(CPU(cpu
), 1);
2888 void helper_booke206_tlbflush(CPUPPCState
*env
, uint32_t type
)
2893 flags
|= BOOKE206_FLUSH_TLB1
;
2897 flags
|= BOOKE206_FLUSH_TLB0
;
2900 booke206_flush_tlb(env
, flags
, 1);
2904 /*****************************************************************************/
2906 #include "exec/softmmu_exec.h"
2908 #define MMUSUFFIX _mmu
2911 #include "exec/softmmu_template.h"
2914 #include "exec/softmmu_template.h"
2917 #include "exec/softmmu_template.h"
2920 #include "exec/softmmu_template.h"
2922 /* try to fill the TLB and return an exception if error. If retaddr is
2923 NULL, it means that the function was called in C code (i.e. not
2924 from generated code or from helper.c) */
2925 /* XXX: fix it to restore all registers */
2926 void tlb_fill(CPUState
*cs
, target_ulong addr
, int is_write
, int mmu_idx
,
2929 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
2930 PowerPCCPUClass
*pcc
= POWERPC_CPU_GET_CLASS(cs
);
2931 CPUPPCState
*env
= &cpu
->env
;
2934 if (pcc
->handle_mmu_fault
) {
2935 ret
= pcc
->handle_mmu_fault(cpu
, addr
, is_write
, mmu_idx
);
2937 ret
= cpu_ppc_handle_mmu_fault(env
, addr
, is_write
, mmu_idx
);
2939 if (unlikely(ret
!= 0)) {
2940 if (likely(retaddr
)) {
2941 /* now we have a real cpu fault */
2942 cpu_restore_state(cs
, retaddr
);
2944 helper_raise_exception_err(env
, cs
->exception_index
, env
->error_code
);