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/>.
19 #include "qemu/osdep.h"
21 #include "exec/helper-proto.h"
22 #include "sysemu/kvm.h"
24 #include "mmu-hash64.h"
25 #include "mmu-hash32.h"
26 #include "exec/cpu_ldst.h"
30 //#define DEBUG_SOFTWARE_TLB
31 //#define DUMP_PAGE_TABLES
32 //#define FLUSH_ALL_TLBS
35 # define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0)
37 # define LOG_MMU_STATE(cpu) do { } while (0)
40 #ifdef DEBUG_SOFTWARE_TLB
41 # define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
43 # define LOG_SWTLB(...) do { } while (0)
47 # define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
49 # define LOG_BATS(...) do { } while (0)
52 /*****************************************************************************/
53 /* PowerPC MMU emulation */
55 /* Context used internally during MMU translations */
56 typedef struct mmu_ctx_t mmu_ctx_t
;
58 hwaddr raddr
; /* Real address */
59 hwaddr eaddr
; /* Effective address */
60 int prot
; /* Protection bits */
61 hwaddr hash
[2]; /* Pagetable hash values */
62 target_ulong ptem
; /* Virtual segment ID | API */
63 int key
; /* Access key */
64 int nx
; /* Non-execute area */
67 /* Common routines used by software and hardware TLBs emulation */
68 static inline int pte_is_valid(target_ulong pte0
)
70 return pte0
& 0x80000000 ? 1 : 0;
73 static inline void pte_invalidate(target_ulong
*pte0
)
78 #define PTE_PTEM_MASK 0x7FFFFFBF
79 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
81 static int pp_check(int key
, int pp
, int nx
)
85 /* Compute access rights */
108 access
= PAGE_READ
| PAGE_WRITE
;
119 static int check_prot(int prot
, int rw
, int access_type
)
123 if (access_type
== ACCESS_CODE
) {
124 if (prot
& PAGE_EXEC
) {
130 if (prot
& PAGE_WRITE
) {
136 if (prot
& PAGE_READ
) {
146 static inline int ppc6xx_tlb_pte_check(mmu_ctx_t
*ctx
, target_ulong pte0
,
147 target_ulong pte1
, int h
, int rw
, int type
)
149 target_ulong ptem
, mmask
;
150 int access
, ret
, pteh
, ptev
, pp
;
153 /* Check validity and table match */
154 ptev
= pte_is_valid(pte0
);
155 pteh
= (pte0
>> 6) & 1;
156 if (ptev
&& h
== pteh
) {
157 /* Check vsid & api */
158 ptem
= pte0
& PTE_PTEM_MASK
;
159 mmask
= PTE_CHECK_MASK
;
160 pp
= pte1
& 0x00000003;
161 if (ptem
== ctx
->ptem
) {
162 if (ctx
->raddr
!= (hwaddr
)-1ULL) {
163 /* all matches should have equal RPN, WIMG & PP */
164 if ((ctx
->raddr
& mmask
) != (pte1
& mmask
)) {
165 qemu_log_mask(CPU_LOG_MMU
, "Bad RPN/WIMG/PP\n");
169 /* Compute access rights */
170 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
171 /* Keep the matching PTE informations */
174 ret
= check_prot(ctx
->prot
, rw
, type
);
177 qemu_log_mask(CPU_LOG_MMU
, "PTE access granted !\n");
179 /* Access right violation */
180 qemu_log_mask(CPU_LOG_MMU
, "PTE access rejected\n");
188 static int pte_update_flags(mmu_ctx_t
*ctx
, target_ulong
*pte1p
,
193 /* Update page flags */
194 if (!(*pte1p
& 0x00000100)) {
195 /* Update accessed flag */
196 *pte1p
|= 0x00000100;
199 if (!(*pte1p
& 0x00000080)) {
200 if (rw
== 1 && ret
== 0) {
201 /* Update changed flag */
202 *pte1p
|= 0x00000080;
205 /* Force page fault for first write access */
206 ctx
->prot
&= ~PAGE_WRITE
;
213 /* Software driven TLB helpers */
214 static inline int ppc6xx_tlb_getnum(CPUPPCState
*env
, target_ulong eaddr
,
215 int way
, int is_code
)
219 /* Select TLB num in a way from address */
220 nr
= (eaddr
>> TARGET_PAGE_BITS
) & (env
->tlb_per_way
- 1);
222 nr
+= env
->tlb_per_way
* way
;
223 /* 6xx have separate TLBs for instructions and data */
224 if (is_code
&& env
->id_tlbs
== 1) {
231 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState
*env
)
233 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
237 /* LOG_SWTLB("Invalidate all TLBs\n"); */
238 /* Invalidate all defined software TLB */
240 if (env
->id_tlbs
== 1) {
243 for (nr
= 0; nr
< max
; nr
++) {
244 tlb
= &env
->tlb
.tlb6
[nr
];
245 pte_invalidate(&tlb
->pte0
);
247 tlb_flush(CPU(cpu
), 1);
250 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState
*env
,
252 int is_code
, int match_epn
)
254 #if !defined(FLUSH_ALL_TLBS)
255 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
259 /* Invalidate ITLB + DTLB, all ways */
260 for (way
= 0; way
< env
->nb_ways
; way
++) {
261 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
, is_code
);
262 tlb
= &env
->tlb
.tlb6
[nr
];
263 if (pte_is_valid(tlb
->pte0
) && (match_epn
== 0 || eaddr
== tlb
->EPN
)) {
264 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx
"\n", nr
,
266 pte_invalidate(&tlb
->pte0
);
267 tlb_flush_page(cs
, tlb
->EPN
);
271 /* XXX: PowerPC specification say this is valid as well */
272 ppc6xx_tlb_invalidate_all(env
);
276 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState
*env
,
277 target_ulong eaddr
, int is_code
)
279 ppc6xx_tlb_invalidate_virt2(env
, eaddr
, is_code
, 0);
282 static void ppc6xx_tlb_store(CPUPPCState
*env
, target_ulong EPN
, int way
,
283 int is_code
, target_ulong pte0
, target_ulong pte1
)
288 nr
= ppc6xx_tlb_getnum(env
, EPN
, way
, is_code
);
289 tlb
= &env
->tlb
.tlb6
[nr
];
290 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
291 " PTE1 " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
, EPN
, pte0
, pte1
);
292 /* Invalidate any pending reference in QEMU for this virtual address */
293 ppc6xx_tlb_invalidate_virt2(env
, EPN
, is_code
, 1);
297 /* Store last way for LRU mechanism */
301 static inline int ppc6xx_tlb_check(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
302 target_ulong eaddr
, int rw
, int access_type
)
309 ret
= -1; /* No TLB found */
310 for (way
= 0; way
< env
->nb_ways
; way
++) {
311 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
,
312 access_type
== ACCESS_CODE
? 1 : 0);
313 tlb
= &env
->tlb
.tlb6
[nr
];
314 /* This test "emulates" the PTE index match for hardware TLBs */
315 if ((eaddr
& TARGET_PAGE_MASK
) != tlb
->EPN
) {
316 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx
" " TARGET_FMT_lx
317 "] <> " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
,
318 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
319 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
, eaddr
);
322 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx
" <> " TARGET_FMT_lx
" "
323 TARGET_FMT_lx
" %c %c\n", nr
, env
->nb_tlb
,
324 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
325 tlb
->EPN
, eaddr
, tlb
->pte1
,
326 rw
? 'S' : 'L', access_type
== ACCESS_CODE
? 'I' : 'D');
327 switch (ppc6xx_tlb_pte_check(ctx
, tlb
->pte0
, tlb
->pte1
, 0, rw
, access_type
)) {
329 /* TLB inconsistency */
332 /* Access violation */
342 /* XXX: we should go on looping to check all TLBs consistency
343 * but we can speed-up the whole thing as the
344 * result would be undefined if TLBs are not consistent.
353 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx
" prot=%01x ret=%d\n",
354 ctx
->raddr
& TARGET_PAGE_MASK
, ctx
->prot
, ret
);
355 /* Update page flags */
356 pte_update_flags(ctx
, &env
->tlb
.tlb6
[best
].pte1
, ret
, rw
);
362 /* Perform BAT hit & translation */
363 static inline void bat_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
364 int *validp
, int *protp
, target_ulong
*BATu
,
370 bl
= (*BATu
& 0x00001FFC) << 15;
373 if (((msr_pr
== 0) && (*BATu
& 0x00000002)) ||
374 ((msr_pr
!= 0) && (*BATu
& 0x00000001))) {
376 pp
= *BATl
& 0x00000003;
378 prot
= PAGE_READ
| PAGE_EXEC
;
389 static int get_bat_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
390 target_ulong
virtual, int rw
, int type
)
392 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
393 target_ulong BEPIl
, BEPIu
, bl
;
397 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx
"\n", __func__
,
398 type
== ACCESS_CODE
? 'I' : 'D', virtual);
401 BATlt
= env
->IBAT
[1];
402 BATut
= env
->IBAT
[0];
405 BATlt
= env
->DBAT
[1];
406 BATut
= env
->DBAT
[0];
409 for (i
= 0; i
< env
->nb_BATs
; i
++) {
412 BEPIu
= *BATu
& 0xF0000000;
413 BEPIl
= *BATu
& 0x0FFE0000;
414 bat_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
415 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
416 " BATl " TARGET_FMT_lx
"\n", __func__
,
417 type
== ACCESS_CODE
? 'I' : 'D', i
, virtual, *BATu
, *BATl
);
418 if ((virtual & 0xF0000000) == BEPIu
&&
419 ((virtual & 0x0FFE0000) & ~bl
) == BEPIl
) {
422 /* Get physical address */
423 ctx
->raddr
= (*BATl
& 0xF0000000) |
424 ((virtual & 0x0FFE0000 & bl
) | (*BATl
& 0x0FFE0000)) |
425 (virtual & 0x0001F000);
426 /* Compute access rights */
428 ret
= check_prot(ctx
->prot
, rw
, type
);
430 LOG_BATS("BAT %d match: r " TARGET_FMT_plx
" prot=%c%c\n",
431 i
, ctx
->raddr
, ctx
->prot
& PAGE_READ
? 'R' : '-',
432 ctx
->prot
& PAGE_WRITE
? 'W' : '-');
439 #if defined(DEBUG_BATS)
440 if (qemu_log_enabled()) {
441 LOG_BATS("no BAT match for " TARGET_FMT_lx
":\n", virtual);
442 for (i
= 0; i
< 4; i
++) {
445 BEPIu
= *BATu
& 0xF0000000;
446 BEPIl
= *BATu
& 0x0FFE0000;
447 bl
= (*BATu
& 0x00001FFC) << 15;
448 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
449 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
450 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
451 __func__
, type
== ACCESS_CODE
? 'I' : 'D', i
, virtual,
452 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
461 /* Perform segment based translation */
462 static inline int get_segment_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
463 target_ulong eaddr
, int rw
, int type
)
467 int ds
, pr
, target_page_bits
;
469 target_ulong sr
, pgidx
;
474 sr
= env
->sr
[eaddr
>> 28];
475 ctx
->key
= (((sr
& 0x20000000) && (pr
!= 0)) ||
476 ((sr
& 0x40000000) && (pr
== 0))) ? 1 : 0;
477 ds
= sr
& 0x80000000 ? 1 : 0;
478 ctx
->nx
= sr
& 0x10000000 ? 1 : 0;
479 vsid
= sr
& 0x00FFFFFF;
480 target_page_bits
= TARGET_PAGE_BITS
;
481 qemu_log_mask(CPU_LOG_MMU
,
482 "Check segment v=" TARGET_FMT_lx
" %d " TARGET_FMT_lx
483 " nip=" 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 qemu_log_mask(CPU_LOG_MMU
,
492 "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx
"\n",
493 ctx
->key
, ds
, ctx
->nx
, vsid
);
496 /* Check if instruction fetch is allowed, if needed */
497 if (type
!= ACCESS_CODE
|| ctx
->nx
== 0) {
498 /* Page address translation */
499 qemu_log_mask(CPU_LOG_MMU
, "htab_base " TARGET_FMT_plx
500 " htab_mask " TARGET_FMT_plx
501 " hash " TARGET_FMT_plx
"\n",
502 env
->htab_base
, env
->htab_mask
, hash
);
504 ctx
->hash
[1] = ~hash
;
506 /* Initialize real address with an invalid value */
507 ctx
->raddr
= (hwaddr
)-1ULL;
508 /* Software TLB search */
509 ret
= ppc6xx_tlb_check(env
, ctx
, eaddr
, rw
, type
);
510 #if defined(DUMP_PAGE_TABLES)
511 if (qemu_log_mask(CPU_LOG_MMU
)) {
513 uint32_t a0
, a1
, a2
, a3
;
515 qemu_log("Page table: " TARGET_FMT_plx
" len " TARGET_FMT_plx
516 "\n", sdr
, mask
+ 0x80);
517 for (curaddr
= sdr
; curaddr
< (sdr
+ mask
+ 0x80);
519 a0
= ldl_phys(curaddr
);
520 a1
= ldl_phys(curaddr
+ 4);
521 a2
= ldl_phys(curaddr
+ 8);
522 a3
= ldl_phys(curaddr
+ 12);
523 if (a0
!= 0 || a1
!= 0 || a2
!= 0 || a3
!= 0) {
524 qemu_log(TARGET_FMT_plx
": %08x %08x %08x %08x\n",
525 curaddr
, a0
, a1
, a2
, a3
);
531 qemu_log_mask(CPU_LOG_MMU
, "No access allowed\n");
537 qemu_log_mask(CPU_LOG_MMU
, "direct store...\n");
538 /* Direct-store segment : absolutely *BUGGY* for now */
540 /* Direct-store implies a 32-bit MMU.
541 * Check the Segment Register's bus unit ID (BUID).
543 sr
= env
->sr
[eaddr
>> 28];
544 if ((sr
& 0x1FF00000) >> 20 == 0x07f) {
545 /* Memory-forced I/O controller interface access */
546 /* If T=1 and BUID=x'07F', the 601 performs a memory access
547 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
549 ctx
->raddr
= ((sr
& 0xF) << 28) | (eaddr
& 0x0FFFFFFF);
550 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
556 /* Integer load/store : only access allowed */
559 /* No code fetch is allowed in direct-store areas */
562 /* Floating point load/store */
565 /* lwarx, ldarx or srwcx. */
568 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
569 /* Should make the instruction do no-op.
570 * As it already do no-op, it's quite easy :-)
578 qemu_log_mask(CPU_LOG_MMU
, "ERROR: instruction should not need "
579 "address translation\n");
582 if ((rw
== 1 || ctx
->key
!= 1) && (rw
== 0 || ctx
->key
!= 0)) {
593 /* Generic TLB check function for embedded PowerPC implementations */
594 static int ppcemb_tlb_check(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
596 target_ulong address
, uint32_t pid
, int ext
,
601 /* Check valid flag */
602 if (!(tlb
->prot
& PAGE_VALID
)) {
605 mask
= ~(tlb
->size
- 1);
606 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx
" PID %u <=> " TARGET_FMT_lx
607 " " TARGET_FMT_lx
" %u %x\n", __func__
, i
, address
, pid
, tlb
->EPN
,
608 mask
, (uint32_t)tlb
->PID
, tlb
->prot
);
610 if (tlb
->PID
!= 0 && tlb
->PID
!= pid
) {
613 /* Check effective address */
614 if ((address
& mask
) != tlb
->EPN
) {
617 *raddrp
= (tlb
->RPN
& mask
) | (address
& ~mask
);
619 /* Extend the physical address to 36 bits */
620 *raddrp
|= (uint64_t)(tlb
->RPN
& 0xF) << 32;
626 /* Generic TLB search function for PowerPC embedded implementations */
627 static int ppcemb_tlb_search(CPUPPCState
*env
, target_ulong address
,
634 /* Default return value is no match */
636 for (i
= 0; i
< env
->nb_tlb
; i
++) {
637 tlb
= &env
->tlb
.tlbe
[i
];
638 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
, pid
, 0, i
) == 0) {
647 /* Helpers specific to PowerPC 40x implementations */
648 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState
*env
)
650 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
654 for (i
= 0; i
< env
->nb_tlb
; i
++) {
655 tlb
= &env
->tlb
.tlbe
[i
];
656 tlb
->prot
&= ~PAGE_VALID
;
658 tlb_flush(CPU(cpu
), 1);
661 static int mmu40x_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
662 target_ulong address
, int rw
,
667 int i
, ret
, zsel
, zpr
, pr
;
670 raddr
= (hwaddr
)-1ULL;
672 for (i
= 0; i
< env
->nb_tlb
; i
++) {
673 tlb
= &env
->tlb
.tlbe
[i
];
674 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
675 env
->spr
[SPR_40x_PID
], 0, i
) < 0) {
678 zsel
= (tlb
->attr
>> 4) & 0xF;
679 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (30 - (2 * zsel
))) & 0x3;
680 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
681 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
682 /* Check execute enable bit */
690 /* All accesses granted */
691 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
696 /* Raise Zone protection fault. */
697 env
->spr
[SPR_40x_ESR
] = 1 << 22;
705 /* Check from TLB entry */
706 ctx
->prot
= tlb
->prot
;
707 ret
= check_prot(ctx
->prot
, rw
, access_type
);
709 env
->spr
[SPR_40x_ESR
] = 0;
715 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
716 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
721 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
722 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
727 void store_40x_sler(CPUPPCState
*env
, uint32_t val
)
729 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
731 /* XXX: TO BE FIXED */
732 if (val
!= 0x00000000) {
733 cpu_abort(CPU(cpu
), "Little-endian regions are not supported by now\n");
735 env
->spr
[SPR_405_SLER
] = val
;
738 static inline int mmubooke_check_tlb(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
739 hwaddr
*raddr
, int *prot
,
740 target_ulong address
, int rw
,
741 int access_type
, int i
)
745 if (ppcemb_tlb_check(env
, tlb
, raddr
, address
,
746 env
->spr
[SPR_BOOKE_PID
],
747 !env
->nb_pids
, i
) >= 0) {
751 if (env
->spr
[SPR_BOOKE_PID1
] &&
752 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
753 env
->spr
[SPR_BOOKE_PID1
], 0, i
) >= 0) {
757 if (env
->spr
[SPR_BOOKE_PID2
] &&
758 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
759 env
->spr
[SPR_BOOKE_PID2
], 0, i
) >= 0) {
763 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
769 prot2
= tlb
->prot
& 0xF;
771 prot2
= (tlb
->prot
>> 4) & 0xF;
774 /* Check the address space */
775 if (access_type
== ACCESS_CODE
) {
776 if (msr_ir
!= (tlb
->attr
& 1)) {
777 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
782 if (prot2
& PAGE_EXEC
) {
783 LOG_SWTLB("%s: good TLB!\n", __func__
);
787 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
790 if (msr_dr
!= (tlb
->attr
& 1)) {
791 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
796 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
797 LOG_SWTLB("%s: found TLB!\n", __func__
);
801 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
808 static int mmubooke_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
809 target_ulong address
, int rw
,
817 raddr
= (hwaddr
)-1ULL;
818 for (i
= 0; i
< env
->nb_tlb
; i
++) {
819 tlb
= &env
->tlb
.tlbe
[i
];
820 ret
= mmubooke_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
, rw
,
829 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
830 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
833 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
834 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
840 static void booke206_flush_tlb(CPUPPCState
*env
, int flags
,
841 const int check_iprot
)
843 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
846 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
848 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
849 if (flags
& (1 << i
)) {
850 tlb_size
= booke206_tlb_size(env
, i
);
851 for (j
= 0; j
< tlb_size
; j
++) {
852 if (!check_iprot
|| !(tlb
[j
].mas1
& MAS1_IPROT
)) {
853 tlb
[j
].mas1
&= ~MAS1_VALID
;
857 tlb
+= booke206_tlb_size(env
, i
);
860 tlb_flush(CPU(cpu
), 1);
863 static hwaddr
booke206_tlb_to_page_size(CPUPPCState
*env
,
868 tlbm_size
= (tlb
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
870 return 1024ULL << tlbm_size
;
873 /* TLB check function for MAS based SoftTLBs */
874 static int ppcmas_tlb_check(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
875 hwaddr
*raddrp
, target_ulong address
,
882 /* In 32bit mode we can only address 32bit EAs */
883 address
= (uint32_t)address
;
886 /* Check valid flag */
887 if (!(tlb
->mas1
& MAS1_VALID
)) {
891 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
892 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx
" PID=0x%x MAS1=0x%x MAS2=0x%"
893 PRIx64
" mask=0x" TARGET_FMT_lx
" MAS7_3=0x%" PRIx64
" MAS8=%x\n",
894 __func__
, address
, pid
, tlb
->mas1
, tlb
->mas2
, mask
, tlb
->mas7_3
,
898 tlb_pid
= (tlb
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
;
899 if (tlb_pid
!= 0 && tlb_pid
!= pid
) {
903 /* Check effective address */
904 if ((address
& mask
) != (tlb
->mas2
& MAS2_EPN_MASK
)) {
909 *raddrp
= (tlb
->mas7_3
& mask
) | (address
& ~mask
);
915 static int mmubooke206_check_tlb(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
916 hwaddr
*raddr
, int *prot
,
917 target_ulong address
, int rw
,
923 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
,
924 env
->spr
[SPR_BOOKE_PID
]) >= 0) {
928 if (env
->spr
[SPR_BOOKE_PID1
] &&
929 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
930 env
->spr
[SPR_BOOKE_PID1
]) >= 0) {
934 if (env
->spr
[SPR_BOOKE_PID2
] &&
935 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
936 env
->spr
[SPR_BOOKE_PID2
]) >= 0) {
940 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
946 if (tlb
->mas7_3
& MAS3_UR
) {
949 if (tlb
->mas7_3
& MAS3_UW
) {
952 if (tlb
->mas7_3
& MAS3_UX
) {
956 if (tlb
->mas7_3
& MAS3_SR
) {
959 if (tlb
->mas7_3
& MAS3_SW
) {
962 if (tlb
->mas7_3
& MAS3_SX
) {
967 /* Check the address space and permissions */
968 if (access_type
== ACCESS_CODE
) {
969 if (msr_ir
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
970 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
975 if (prot2
& PAGE_EXEC
) {
976 LOG_SWTLB("%s: good TLB!\n", __func__
);
980 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
983 if (msr_dr
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
984 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
989 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
990 LOG_SWTLB("%s: found TLB!\n", __func__
);
994 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
1001 static int mmubooke206_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1002 target_ulong address
, int rw
,
1010 raddr
= (hwaddr
)-1ULL;
1012 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1013 int ways
= booke206_tlb_ways(env
, i
);
1015 for (j
= 0; j
< ways
; j
++) {
1016 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
1020 ret
= mmubooke206_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
,
1032 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
1033 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1036 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
1037 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
1043 static const char *book3e_tsize_to_str
[32] = {
1044 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1045 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1046 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1050 static void mmubooke_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1053 ppcemb_tlb_t
*entry
;
1056 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1057 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1061 cpu_fprintf(f
, "\nTLB:\n");
1062 cpu_fprintf(f
, "Effective Physical Size PID Prot "
1065 entry
= &env
->tlb
.tlbe
[0];
1066 for (i
= 0; i
< env
->nb_tlb
; i
++, entry
++) {
1069 uint64_t size
= (uint64_t)entry
->size
;
1072 /* Check valid flag */
1073 if (!(entry
->prot
& PAGE_VALID
)) {
1077 mask
= ~(entry
->size
- 1);
1078 ea
= entry
->EPN
& mask
;
1079 pa
= entry
->RPN
& mask
;
1080 /* Extend the physical address to 36 bits */
1081 pa
|= (hwaddr
)(entry
->RPN
& 0xF) << 32;
1084 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"M", size
/ 1024);
1086 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"k", size
);
1088 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %s %-5u %08x %08x\n",
1089 (uint64_t)ea
, (uint64_t)pa
, size_buf
, (uint32_t)entry
->PID
,
1090 entry
->prot
, entry
->attr
);
1095 static void mmubooke206_dump_one_tlb(FILE *f
, fprintf_function cpu_fprintf
,
1096 CPUPPCState
*env
, int tlbn
, int offset
,
1099 ppcmas_tlb_t
*entry
;
1102 cpu_fprintf(f
, "\nTLB%d:\n", tlbn
);
1103 cpu_fprintf(f
, "Effective Physical Size TID TS SRWX"
1104 " URWX WIMGE U0123\n");
1106 entry
= &env
->tlb
.tlbm
[offset
];
1107 for (i
= 0; i
< tlbsize
; i
++, entry
++) {
1108 hwaddr ea
, pa
, size
;
1111 if (!(entry
->mas1
& MAS1_VALID
)) {
1115 tsize
= (entry
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1116 size
= 1024ULL << tsize
;
1117 ea
= entry
->mas2
& ~(size
- 1);
1118 pa
= entry
->mas7_3
& ~(size
- 1);
1120 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %4s %-5u %1u S%c%c%c"
1121 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1122 (uint64_t)ea
, (uint64_t)pa
,
1123 book3e_tsize_to_str
[tsize
],
1124 (entry
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
,
1125 (entry
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
,
1126 entry
->mas7_3
& MAS3_SR
? 'R' : '-',
1127 entry
->mas7_3
& MAS3_SW
? 'W' : '-',
1128 entry
->mas7_3
& MAS3_SX
? 'X' : '-',
1129 entry
->mas7_3
& MAS3_UR
? 'R' : '-',
1130 entry
->mas7_3
& MAS3_UW
? 'W' : '-',
1131 entry
->mas7_3
& MAS3_UX
? 'X' : '-',
1132 entry
->mas2
& MAS2_W
? 'W' : '-',
1133 entry
->mas2
& MAS2_I
? 'I' : '-',
1134 entry
->mas2
& MAS2_M
? 'M' : '-',
1135 entry
->mas2
& MAS2_G
? 'G' : '-',
1136 entry
->mas2
& MAS2_E
? 'E' : '-',
1137 entry
->mas7_3
& MAS3_U0
? '0' : '-',
1138 entry
->mas7_3
& MAS3_U1
? '1' : '-',
1139 entry
->mas7_3
& MAS3_U2
? '2' : '-',
1140 entry
->mas7_3
& MAS3_U3
? '3' : '-');
1144 static void mmubooke206_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1150 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1151 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1155 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1156 int size
= booke206_tlb_size(env
, i
);
1162 mmubooke206_dump_one_tlb(f
, cpu_fprintf
, env
, i
, offset
, size
);
1167 static void mmu6xx_dump_BATs(FILE *f
, fprintf_function cpu_fprintf
,
1168 CPUPPCState
*env
, int type
)
1170 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
1171 target_ulong BEPIl
, BEPIu
, bl
;
1176 BATlt
= env
->IBAT
[1];
1177 BATut
= env
->IBAT
[0];
1180 BATlt
= env
->DBAT
[1];
1181 BATut
= env
->DBAT
[0];
1185 for (i
= 0; i
< env
->nb_BATs
; i
++) {
1188 BEPIu
= *BATu
& 0xF0000000;
1189 BEPIl
= *BATu
& 0x0FFE0000;
1190 bl
= (*BATu
& 0x00001FFC) << 15;
1191 cpu_fprintf(f
, "%s BAT%d BATu " TARGET_FMT_lx
1192 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
1193 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
1194 type
== ACCESS_CODE
? "code" : "data", i
,
1195 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
1199 static void mmu6xx_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1204 int type
, way
, entry
, i
;
1206 cpu_fprintf(f
, "HTAB base = 0x%"HWADDR_PRIx
"\n", env
->htab_base
);
1207 cpu_fprintf(f
, "HTAB mask = 0x%"HWADDR_PRIx
"\n", env
->htab_mask
);
1209 cpu_fprintf(f
, "\nSegment registers:\n");
1210 for (i
= 0; i
< 32; i
++) {
1212 if (sr
& 0x80000000) {
1213 cpu_fprintf(f
, "%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1214 "CNTLR_SPEC=0x%05x\n", i
,
1215 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1216 sr
& 0x20000000 ? 1 : 0, (uint32_t)((sr
>> 20) & 0x1FF),
1217 (uint32_t)(sr
& 0xFFFFF));
1219 cpu_fprintf(f
, "%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i
,
1220 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1221 sr
& 0x20000000 ? 1 : 0, sr
& 0x10000000 ? 1 : 0,
1222 (uint32_t)(sr
& 0x00FFFFFF));
1226 cpu_fprintf(f
, "\nBATs:\n");
1227 mmu6xx_dump_BATs(f
, cpu_fprintf
, env
, ACCESS_INT
);
1228 mmu6xx_dump_BATs(f
, cpu_fprintf
, env
, ACCESS_CODE
);
1230 if (env
->id_tlbs
!= 1) {
1231 cpu_fprintf(f
, "ERROR: 6xx MMU should have separated TLB"
1232 " for code and data\n");
1235 cpu_fprintf(f
, "\nTLBs [EPN EPN + SIZE]\n");
1237 for (type
= 0; type
< 2; type
++) {
1238 for (way
= 0; way
< env
->nb_ways
; way
++) {
1239 for (entry
= env
->nb_tlb
* type
+ env
->tlb_per_way
* way
;
1240 entry
< (env
->nb_tlb
* type
+ env
->tlb_per_way
* (way
+ 1));
1243 tlb
= &env
->tlb
.tlb6
[entry
];
1244 cpu_fprintf(f
, "%s TLB %02d/%02d way:%d %s ["
1245 TARGET_FMT_lx
" " TARGET_FMT_lx
"]\n",
1246 type
? "code" : "data", entry
% env
->nb_tlb
,
1248 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
1249 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
);
1255 void dump_mmu(FILE *f
, fprintf_function cpu_fprintf
, CPUPPCState
*env
)
1257 switch (env
->mmu_model
) {
1258 case POWERPC_MMU_BOOKE
:
1259 mmubooke_dump_mmu(f
, cpu_fprintf
, env
);
1261 case POWERPC_MMU_BOOKE206
:
1262 mmubooke206_dump_mmu(f
, cpu_fprintf
, env
);
1264 case POWERPC_MMU_SOFT_6xx
:
1265 case POWERPC_MMU_SOFT_74xx
:
1266 mmu6xx_dump_mmu(f
, cpu_fprintf
, env
);
1268 #if defined(TARGET_PPC64)
1269 case POWERPC_MMU_64B
:
1270 case POWERPC_MMU_2_03
:
1271 case POWERPC_MMU_2_06
:
1272 case POWERPC_MMU_2_06a
:
1273 case POWERPC_MMU_2_07
:
1274 case POWERPC_MMU_2_07a
:
1275 dump_slb(f
, cpu_fprintf
, ppc_env_get_cpu(env
));
1279 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented\n", __func__
);
1283 static inline int check_physical(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1284 target_ulong eaddr
, int rw
)
1289 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1291 switch (env
->mmu_model
) {
1292 case POWERPC_MMU_SOFT_6xx
:
1293 case POWERPC_MMU_SOFT_74xx
:
1294 case POWERPC_MMU_SOFT_4xx
:
1295 case POWERPC_MMU_REAL
:
1296 case POWERPC_MMU_BOOKE
:
1297 ctx
->prot
|= PAGE_WRITE
;
1300 case POWERPC_MMU_SOFT_4xx_Z
:
1301 if (unlikely(msr_pe
!= 0)) {
1302 /* 403 family add some particular protections,
1303 * using PBL/PBU registers for accesses with no translation.
1306 /* Check PLB validity */
1307 (env
->pb
[0] < env
->pb
[1] &&
1308 /* and address in plb area */
1309 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1310 (env
->pb
[2] < env
->pb
[3] &&
1311 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1312 if (in_plb
^ msr_px
) {
1313 /* Access in protected area */
1315 /* Access is not allowed */
1319 /* Read-write access is allowed */
1320 ctx
->prot
|= PAGE_WRITE
;
1326 /* Caller's checks mean we should never get here for other models */
1334 static int get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1335 target_ulong eaddr
, int rw
, int access_type
)
1337 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1339 bool real_mode
= (access_type
== ACCESS_CODE
&& msr_ir
== 0)
1340 || (access_type
!= ACCESS_CODE
&& msr_dr
== 0);
1343 qemu_log("%s\n", __func__
);
1346 switch (env
->mmu_model
) {
1347 case POWERPC_MMU_SOFT_6xx
:
1348 case POWERPC_MMU_SOFT_74xx
:
1350 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1352 /* Try to find a BAT */
1353 if (env
->nb_BATs
!= 0) {
1354 ret
= get_bat_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1357 /* We didn't match any BAT entry or don't have BATs */
1358 ret
= get_segment_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1363 case POWERPC_MMU_SOFT_4xx
:
1364 case POWERPC_MMU_SOFT_4xx_Z
:
1366 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1368 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1372 case POWERPC_MMU_BOOKE
:
1373 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1376 case POWERPC_MMU_BOOKE206
:
1377 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1380 case POWERPC_MMU_MPC8xx
:
1382 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1384 case POWERPC_MMU_REAL
:
1386 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1388 cpu_abort(CPU(cpu
), "PowerPC in real mode do not do any translation\n");
1392 cpu_abort(CPU(cpu
), "Unknown or invalid MMU model\n");
1396 qemu_log("%s address " TARGET_FMT_lx
" => %d " TARGET_FMT_plx
"\n",
1397 __func__
, eaddr
, ret
, ctx
->raddr
);
1403 hwaddr
ppc_cpu_get_phys_page_debug(CPUState
*cs
, vaddr addr
)
1405 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
1406 CPUPPCState
*env
= &cpu
->env
;
1409 switch (env
->mmu_model
) {
1410 #if defined(TARGET_PPC64)
1411 case POWERPC_MMU_64B
:
1412 case POWERPC_MMU_2_03
:
1413 case POWERPC_MMU_2_06
:
1414 case POWERPC_MMU_2_06a
:
1415 case POWERPC_MMU_2_07
:
1416 case POWERPC_MMU_2_07a
:
1417 return ppc_hash64_get_phys_page_debug(cpu
, addr
);
1420 case POWERPC_MMU_32B
:
1421 case POWERPC_MMU_601
:
1422 return ppc_hash32_get_phys_page_debug(cpu
, addr
);
1428 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0)) {
1430 /* Some MMUs have separate TLBs for code and data. If we only try an
1431 * ACCESS_INT, we may not be able to read instructions mapped by code
1432 * TLBs, so we also try a ACCESS_CODE.
1434 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0,
1435 ACCESS_CODE
) != 0)) {
1440 return ctx
.raddr
& TARGET_PAGE_MASK
;
1443 static void booke206_update_mas_tlb_miss(CPUPPCState
*env
, target_ulong address
,
1446 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
1447 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
1448 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
1449 env
->spr
[SPR_BOOKE_MAS3
] = 0;
1450 env
->spr
[SPR_BOOKE_MAS6
] = 0;
1451 env
->spr
[SPR_BOOKE_MAS7
] = 0;
1454 if (((rw
== 2) && msr_ir
) || ((rw
!= 2) && msr_dr
)) {
1455 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
1456 env
->spr
[SPR_BOOKE_MAS6
] |= MAS6_SAS
;
1459 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_VALID
;
1460 env
->spr
[SPR_BOOKE_MAS2
] |= address
& MAS2_EPN_MASK
;
1462 switch (env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TIDSELD_PIDZ
) {
1463 case MAS4_TIDSELD_PID0
:
1464 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID
] << MAS1_TID_SHIFT
;
1466 case MAS4_TIDSELD_PID1
:
1467 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID1
] << MAS1_TID_SHIFT
;
1469 case MAS4_TIDSELD_PID2
:
1470 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID2
] << MAS1_TID_SHIFT
;
1474 env
->spr
[SPR_BOOKE_MAS6
] |= env
->spr
[SPR_BOOKE_PID
] << 16;
1476 /* next victim logic */
1477 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
1479 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
1480 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
1483 /* Perform address translation */
1484 static int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
,
1485 int rw
, int mmu_idx
)
1487 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1488 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
1496 access_type
= ACCESS_CODE
;
1499 access_type
= env
->access_type
;
1501 ret
= get_physical_address(env
, &ctx
, address
, rw
, access_type
);
1503 tlb_set_page(cs
, address
& TARGET_PAGE_MASK
,
1504 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1505 mmu_idx
, TARGET_PAGE_SIZE
);
1507 } else if (ret
< 0) {
1509 if (access_type
== ACCESS_CODE
) {
1512 /* No matches in page tables or TLB */
1513 switch (env
->mmu_model
) {
1514 case POWERPC_MMU_SOFT_6xx
:
1515 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1516 env
->error_code
= 1 << 18;
1517 env
->spr
[SPR_IMISS
] = address
;
1518 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1520 case POWERPC_MMU_SOFT_74xx
:
1521 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1523 case POWERPC_MMU_SOFT_4xx
:
1524 case POWERPC_MMU_SOFT_4xx_Z
:
1525 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1526 env
->error_code
= 0;
1527 env
->spr
[SPR_40x_DEAR
] = address
;
1528 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1530 case POWERPC_MMU_BOOKE206
:
1531 booke206_update_mas_tlb_miss(env
, address
, rw
);
1533 case POWERPC_MMU_BOOKE
:
1534 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1535 env
->error_code
= 0;
1536 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1538 case POWERPC_MMU_MPC8xx
:
1540 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1542 case POWERPC_MMU_REAL
:
1543 cpu_abort(cs
, "PowerPC in real mode should never raise "
1544 "any MMU exceptions\n");
1547 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1552 /* Access rights violation */
1553 cs
->exception_index
= POWERPC_EXCP_ISI
;
1554 env
->error_code
= 0x08000000;
1557 /* No execute protection violation */
1558 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1559 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1560 env
->spr
[SPR_BOOKE_ESR
] = 0x00000000;
1562 cs
->exception_index
= POWERPC_EXCP_ISI
;
1563 env
->error_code
= 0x10000000;
1566 /* Direct store exception */
1567 /* No code fetch is allowed in direct-store areas */
1568 cs
->exception_index
= POWERPC_EXCP_ISI
;
1569 env
->error_code
= 0x10000000;
1575 /* No matches in page tables or TLB */
1576 switch (env
->mmu_model
) {
1577 case POWERPC_MMU_SOFT_6xx
:
1579 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1580 env
->error_code
= 1 << 16;
1582 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1583 env
->error_code
= 0;
1585 env
->spr
[SPR_DMISS
] = address
;
1586 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1588 env
->error_code
|= ctx
.key
<< 19;
1589 env
->spr
[SPR_HASH1
] = env
->htab_base
+
1590 get_pteg_offset32(cpu
, ctx
.hash
[0]);
1591 env
->spr
[SPR_HASH2
] = env
->htab_base
+
1592 get_pteg_offset32(cpu
, ctx
.hash
[1]);
1594 case POWERPC_MMU_SOFT_74xx
:
1596 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1598 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1601 /* Implement LRU algorithm */
1602 env
->error_code
= ctx
.key
<< 19;
1603 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1604 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1605 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1607 case POWERPC_MMU_SOFT_4xx
:
1608 case POWERPC_MMU_SOFT_4xx_Z
:
1609 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1610 env
->error_code
= 0;
1611 env
->spr
[SPR_40x_DEAR
] = address
;
1613 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1615 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1618 case POWERPC_MMU_MPC8xx
:
1620 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1622 case POWERPC_MMU_BOOKE206
:
1623 booke206_update_mas_tlb_miss(env
, address
, rw
);
1625 case POWERPC_MMU_BOOKE
:
1626 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1627 env
->error_code
= 0;
1628 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1629 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1631 case POWERPC_MMU_REAL
:
1632 cpu_abort(cs
, "PowerPC in real mode should never raise "
1633 "any MMU exceptions\n");
1636 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1641 /* Access rights violation */
1642 cs
->exception_index
= POWERPC_EXCP_DSI
;
1643 env
->error_code
= 0;
1644 if (env
->mmu_model
== POWERPC_MMU_SOFT_4xx
1645 || env
->mmu_model
== POWERPC_MMU_SOFT_4xx_Z
) {
1646 env
->spr
[SPR_40x_DEAR
] = address
;
1648 env
->spr
[SPR_40x_ESR
] |= 0x00800000;
1650 } else if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1651 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1652 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1653 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1655 env
->spr
[SPR_DAR
] = address
;
1657 env
->spr
[SPR_DSISR
] = 0x0A000000;
1659 env
->spr
[SPR_DSISR
] = 0x08000000;
1664 /* Direct store exception */
1665 switch (access_type
) {
1667 /* Floating point load/store */
1668 cs
->exception_index
= POWERPC_EXCP_ALIGN
;
1669 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1670 env
->spr
[SPR_DAR
] = address
;
1673 /* lwarx, ldarx or stwcx. */
1674 cs
->exception_index
= POWERPC_EXCP_DSI
;
1675 env
->error_code
= 0;
1676 env
->spr
[SPR_DAR
] = address
;
1678 env
->spr
[SPR_DSISR
] = 0x06000000;
1680 env
->spr
[SPR_DSISR
] = 0x04000000;
1684 /* eciwx or ecowx */
1685 cs
->exception_index
= POWERPC_EXCP_DSI
;
1686 env
->error_code
= 0;
1687 env
->spr
[SPR_DAR
] = address
;
1689 env
->spr
[SPR_DSISR
] = 0x06100000;
1691 env
->spr
[SPR_DSISR
] = 0x04100000;
1695 printf("DSI: invalid exception (%d)\n", ret
);
1696 cs
->exception_index
= POWERPC_EXCP_PROGRAM
;
1698 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1699 env
->spr
[SPR_DAR
] = address
;
1706 printf("%s: set exception to %d %02x\n", __func__
,
1707 cs
->exception
, env
->error_code
);
1715 /*****************************************************************************/
1716 /* BATs management */
1717 #if !defined(FLUSH_ALL_TLBS)
1718 static inline void do_invalidate_BAT(CPUPPCState
*env
, target_ulong BATu
,
1721 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1722 target_ulong base
, end
, page
;
1724 base
= BATu
& ~0x0001FFFF;
1725 end
= base
+ mask
+ 0x00020000;
1726 LOG_BATS("Flush BAT from " TARGET_FMT_lx
" to " TARGET_FMT_lx
" ("
1727 TARGET_FMT_lx
")\n", base
, end
, mask
);
1728 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
1729 tlb_flush_page(cs
, page
);
1731 LOG_BATS("Flush done\n");
1735 static inline void dump_store_bat(CPUPPCState
*env
, char ID
, int ul
, int nr
,
1738 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx
" (" TARGET_FMT_lx
")\n", ID
,
1739 nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1742 void helper_store_ibatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1746 dump_store_bat(env
, 'I', 0, nr
, value
);
1747 if (env
->IBAT
[0][nr
] != value
) {
1748 mask
= (value
<< 15) & 0x0FFE0000UL
;
1749 #if !defined(FLUSH_ALL_TLBS)
1750 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1752 /* When storing valid upper BAT, mask BEPI and BRPN
1753 * and invalidate all TLBs covered by this BAT
1755 mask
= (value
<< 15) & 0x0FFE0000UL
;
1756 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1757 (value
& ~0x0001FFFFUL
& ~mask
);
1758 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1759 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1760 #if !defined(FLUSH_ALL_TLBS)
1761 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1768 void helper_store_ibatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1770 dump_store_bat(env
, 'I', 1, nr
, value
);
1771 env
->IBAT
[1][nr
] = value
;
1774 void helper_store_dbatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1778 dump_store_bat(env
, 'D', 0, nr
, value
);
1779 if (env
->DBAT
[0][nr
] != value
) {
1780 /* When storing valid upper BAT, mask BEPI and BRPN
1781 * and invalidate all TLBs covered by this BAT
1783 mask
= (value
<< 15) & 0x0FFE0000UL
;
1784 #if !defined(FLUSH_ALL_TLBS)
1785 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1787 mask
= (value
<< 15) & 0x0FFE0000UL
;
1788 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1789 (value
& ~0x0001FFFFUL
& ~mask
);
1790 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1791 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1792 #if !defined(FLUSH_ALL_TLBS)
1793 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1800 void helper_store_dbatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1802 dump_store_bat(env
, 'D', 1, nr
, value
);
1803 env
->DBAT
[1][nr
] = value
;
1806 void helper_store_601_batu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1809 #if defined(FLUSH_ALL_TLBS)
1813 dump_store_bat(env
, 'I', 0, nr
, value
);
1814 if (env
->IBAT
[0][nr
] != value
) {
1815 #if defined(FLUSH_ALL_TLBS)
1818 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1819 if (env
->IBAT
[1][nr
] & 0x40) {
1820 /* Invalidate BAT only if it is valid */
1821 #if !defined(FLUSH_ALL_TLBS)
1822 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1827 /* When storing valid upper BAT, mask BEPI and BRPN
1828 * and invalidate all TLBs covered by this BAT
1830 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1831 (value
& ~0x0001FFFFUL
& ~mask
);
1832 env
->DBAT
[0][nr
] = env
->IBAT
[0][nr
];
1833 if (env
->IBAT
[1][nr
] & 0x40) {
1834 #if !defined(FLUSH_ALL_TLBS)
1835 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1840 #if defined(FLUSH_ALL_TLBS)
1848 void helper_store_601_batl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1850 #if !defined(FLUSH_ALL_TLBS)
1856 dump_store_bat(env
, 'I', 1, nr
, value
);
1857 if (env
->IBAT
[1][nr
] != value
) {
1858 #if defined(FLUSH_ALL_TLBS)
1861 if (env
->IBAT
[1][nr
] & 0x40) {
1862 #if !defined(FLUSH_ALL_TLBS)
1863 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1864 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1870 #if !defined(FLUSH_ALL_TLBS)
1871 mask
= (value
<< 17) & 0x0FFE0000UL
;
1872 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1877 env
->IBAT
[1][nr
] = value
;
1878 env
->DBAT
[1][nr
] = value
;
1879 #if defined(FLUSH_ALL_TLBS)
1887 /*****************************************************************************/
1888 /* TLB management */
1889 void ppc_tlb_invalidate_all(CPUPPCState
*env
)
1891 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1893 switch (env
->mmu_model
) {
1894 case POWERPC_MMU_SOFT_6xx
:
1895 case POWERPC_MMU_SOFT_74xx
:
1896 ppc6xx_tlb_invalidate_all(env
);
1898 case POWERPC_MMU_SOFT_4xx
:
1899 case POWERPC_MMU_SOFT_4xx_Z
:
1900 ppc4xx_tlb_invalidate_all(env
);
1902 case POWERPC_MMU_REAL
:
1903 cpu_abort(CPU(cpu
), "No TLB for PowerPC 4xx in real mode\n");
1905 case POWERPC_MMU_MPC8xx
:
1907 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1909 case POWERPC_MMU_BOOKE
:
1910 tlb_flush(CPU(cpu
), 1);
1912 case POWERPC_MMU_BOOKE206
:
1913 booke206_flush_tlb(env
, -1, 0);
1915 case POWERPC_MMU_32B
:
1916 case POWERPC_MMU_601
:
1917 #if defined(TARGET_PPC64)
1918 case POWERPC_MMU_64B
:
1919 case POWERPC_MMU_2_03
:
1920 case POWERPC_MMU_2_06
:
1921 case POWERPC_MMU_2_06a
:
1922 case POWERPC_MMU_2_07
:
1923 case POWERPC_MMU_2_07a
:
1924 #endif /* defined(TARGET_PPC64) */
1925 tlb_flush(CPU(cpu
), 1);
1929 cpu_abort(CPU(cpu
), "Unknown MMU model\n");
1934 void ppc_tlb_invalidate_one(CPUPPCState
*env
, target_ulong addr
)
1936 #if !defined(FLUSH_ALL_TLBS)
1937 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1940 addr
&= TARGET_PAGE_MASK
;
1941 switch (env
->mmu_model
) {
1942 case POWERPC_MMU_SOFT_6xx
:
1943 case POWERPC_MMU_SOFT_74xx
:
1944 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
1945 if (env
->id_tlbs
== 1) {
1946 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
1949 case POWERPC_MMU_32B
:
1950 case POWERPC_MMU_601
:
1951 /* tlbie invalidate TLBs for all segments */
1952 addr
&= ~((target_ulong
)-1ULL << 28);
1954 /* XXX: this case should be optimized,
1955 * giving a mask to tlb_flush_page
1957 tlb_flush_page(cs
, addr
| (0x0 << 28));
1958 tlb_flush_page(cs
, addr
| (0x1 << 28));
1959 tlb_flush_page(cs
, addr
| (0x2 << 28));
1960 tlb_flush_page(cs
, addr
| (0x3 << 28));
1961 tlb_flush_page(cs
, addr
| (0x4 << 28));
1962 tlb_flush_page(cs
, addr
| (0x5 << 28));
1963 tlb_flush_page(cs
, addr
| (0x6 << 28));
1964 tlb_flush_page(cs
, addr
| (0x7 << 28));
1965 tlb_flush_page(cs
, addr
| (0x8 << 28));
1966 tlb_flush_page(cs
, addr
| (0x9 << 28));
1967 tlb_flush_page(cs
, addr
| (0xA << 28));
1968 tlb_flush_page(cs
, addr
| (0xB << 28));
1969 tlb_flush_page(cs
, addr
| (0xC << 28));
1970 tlb_flush_page(cs
, addr
| (0xD << 28));
1971 tlb_flush_page(cs
, addr
| (0xE << 28));
1972 tlb_flush_page(cs
, addr
| (0xF << 28));
1974 #if defined(TARGET_PPC64)
1975 case POWERPC_MMU_64B
:
1976 case POWERPC_MMU_2_03
:
1977 case POWERPC_MMU_2_06
:
1978 case POWERPC_MMU_2_06a
:
1979 case POWERPC_MMU_2_07
:
1980 case POWERPC_MMU_2_07a
:
1981 /* tlbie invalidate TLBs for all segments */
1982 /* XXX: given the fact that there are too many segments to invalidate,
1983 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
1984 * we just invalidate all TLBs
1986 tlb_flush(CPU(cpu
), 1);
1988 #endif /* defined(TARGET_PPC64) */
1990 /* Should never reach here with other MMU models */
1994 ppc_tlb_invalidate_all(env
);
1998 /*****************************************************************************/
1999 /* Special registers manipulation */
2000 void ppc_store_sdr1(CPUPPCState
*env
, target_ulong value
)
2002 qemu_log_mask(CPU_LOG_MMU
, "%s: " TARGET_FMT_lx
"\n", __func__
, value
);
2003 assert(!env
->external_htab
);
2004 env
->spr
[SPR_SDR1
] = value
;
2005 #if defined(TARGET_PPC64)
2006 if (env
->mmu_model
& POWERPC_MMU_64
) {
2007 target_ulong htabsize
= value
& SDR_64_HTABSIZE
;
2009 if (htabsize
> 28) {
2010 fprintf(stderr
, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2011 " stored in SDR1\n", htabsize
);
2014 env
->htab_mask
= (1ULL << (htabsize
+ 18 - 7)) - 1;
2015 env
->htab_base
= value
& SDR_64_HTABORG
;
2017 #endif /* defined(TARGET_PPC64) */
2019 /* FIXME: Should check for valid HTABMASK values */
2020 env
->htab_mask
= ((value
& SDR_32_HTABMASK
) << 16) | 0xFFFF;
2021 env
->htab_base
= value
& SDR_32_HTABORG
;
2025 /* Segment registers load and store */
2026 target_ulong
helper_load_sr(CPUPPCState
*env
, target_ulong sr_num
)
2028 #if defined(TARGET_PPC64)
2029 if (env
->mmu_model
& POWERPC_MMU_64
) {
2034 return env
->sr
[sr_num
];
2037 void helper_store_sr(CPUPPCState
*env
, target_ulong srnum
, target_ulong value
)
2039 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2041 qemu_log_mask(CPU_LOG_MMU
,
2042 "%s: reg=%d " TARGET_FMT_lx
" " TARGET_FMT_lx
"\n", __func__
,
2043 (int)srnum
, value
, env
->sr
[srnum
]);
2044 #if defined(TARGET_PPC64)
2045 if (env
->mmu_model
& POWERPC_MMU_64
) {
2046 uint64_t esid
, vsid
;
2049 esid
= ((uint64_t)(srnum
& 0xf) << 28) | SLB_ESID_V
;
2052 vsid
= (value
& 0xfffffff) << 12;
2054 vsid
|= ((value
>> 27) & 0xf) << 8;
2056 ppc_store_slb(cpu
, srnum
, esid
, vsid
);
2059 if (env
->sr
[srnum
] != value
) {
2060 env
->sr
[srnum
] = value
;
2061 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2062 flusing the whole TLB. */
2063 #if !defined(FLUSH_ALL_TLBS) && 0
2065 target_ulong page
, end
;
2066 /* Invalidate 256 MB of virtual memory */
2067 page
= (16 << 20) * srnum
;
2068 end
= page
+ (16 << 20);
2069 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
2070 tlb_flush_page(CPU(cpu
), page
);
2074 tlb_flush(CPU(cpu
), 1);
2079 /* TLB management */
2080 void helper_tlbia(CPUPPCState
*env
)
2082 ppc_tlb_invalidate_all(env
);
2085 void helper_tlbie(CPUPPCState
*env
, target_ulong addr
)
2087 ppc_tlb_invalidate_one(env
, addr
);
2090 void helper_tlbiva(CPUPPCState
*env
, target_ulong addr
)
2092 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2094 /* tlbiva instruction only exists on BookE */
2095 assert(env
->mmu_model
== POWERPC_MMU_BOOKE
);
2097 cpu_abort(CPU(cpu
), "BookE MMU model is not implemented\n");
2100 /* Software driven TLBs management */
2101 /* PowerPC 602/603 software TLB load instructions helpers */
2102 static void do_6xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2104 target_ulong RPN
, CMP
, EPN
;
2107 RPN
= env
->spr
[SPR_RPA
];
2109 CMP
= env
->spr
[SPR_ICMP
];
2110 EPN
= env
->spr
[SPR_IMISS
];
2112 CMP
= env
->spr
[SPR_DCMP
];
2113 EPN
= env
->spr
[SPR_DMISS
];
2115 way
= (env
->spr
[SPR_SRR1
] >> 17) & 1;
2116 (void)EPN
; /* avoid a compiler warning */
2117 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2118 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2120 /* Store this TLB */
2121 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2122 way
, is_code
, CMP
, RPN
);
2125 void helper_6xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2127 do_6xx_tlb(env
, EPN
, 0);
2130 void helper_6xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2132 do_6xx_tlb(env
, EPN
, 1);
2135 /* PowerPC 74xx software TLB load instructions helpers */
2136 static void do_74xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2138 target_ulong RPN
, CMP
, EPN
;
2141 RPN
= env
->spr
[SPR_PTELO
];
2142 CMP
= env
->spr
[SPR_PTEHI
];
2143 EPN
= env
->spr
[SPR_TLBMISS
] & ~0x3;
2144 way
= env
->spr
[SPR_TLBMISS
] & 0x3;
2145 (void)EPN
; /* avoid a compiler warning */
2146 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2147 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2149 /* Store this TLB */
2150 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2151 way
, is_code
, CMP
, RPN
);
2154 void helper_74xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2156 do_74xx_tlb(env
, EPN
, 0);
2159 void helper_74xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2161 do_74xx_tlb(env
, EPN
, 1);
2164 /*****************************************************************************/
2165 /* PowerPC 601 specific instructions (POWER bridge) */
2167 target_ulong
helper_rac(CPUPPCState
*env
, target_ulong addr
)
2171 target_ulong ret
= 0;
2173 /* We don't have to generate many instances of this instruction,
2174 * as rac is supervisor only.
2176 /* XXX: FIX THIS: Pretend we have no BAT */
2177 nb_BATs
= env
->nb_BATs
;
2179 if (get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) == 0) {
2182 env
->nb_BATs
= nb_BATs
;
2186 static inline target_ulong
booke_tlb_to_page_size(int size
)
2188 return 1024 << (2 * size
);
2191 static inline int booke_page_size_to_tlb(target_ulong page_size
)
2195 switch (page_size
) {
2229 #if defined(TARGET_PPC64)
2230 case 0x000100000000ULL
:
2233 case 0x000400000000ULL
:
2236 case 0x001000000000ULL
:
2239 case 0x004000000000ULL
:
2242 case 0x010000000000ULL
:
2254 /* Helpers for 4xx TLB management */
2255 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2257 #define PPC4XX_TLBHI_V 0x00000040
2258 #define PPC4XX_TLBHI_E 0x00000020
2259 #define PPC4XX_TLBHI_SIZE_MIN 0
2260 #define PPC4XX_TLBHI_SIZE_MAX 7
2261 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2262 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2263 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2265 #define PPC4XX_TLBLO_EX 0x00000200
2266 #define PPC4XX_TLBLO_WR 0x00000100
2267 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2268 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2270 target_ulong
helper_4xx_tlbre_hi(CPUPPCState
*env
, target_ulong entry
)
2276 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2277 tlb
= &env
->tlb
.tlbe
[entry
];
2279 if (tlb
->prot
& PAGE_VALID
) {
2280 ret
|= PPC4XX_TLBHI_V
;
2282 size
= booke_page_size_to_tlb(tlb
->size
);
2283 if (size
< PPC4XX_TLBHI_SIZE_MIN
|| size
> PPC4XX_TLBHI_SIZE_MAX
) {
2284 size
= PPC4XX_TLBHI_SIZE_DEFAULT
;
2286 ret
|= size
<< PPC4XX_TLBHI_SIZE_SHIFT
;
2287 env
->spr
[SPR_40x_PID
] = tlb
->PID
;
2291 target_ulong
helper_4xx_tlbre_lo(CPUPPCState
*env
, target_ulong entry
)
2296 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2297 tlb
= &env
->tlb
.tlbe
[entry
];
2299 if (tlb
->prot
& PAGE_EXEC
) {
2300 ret
|= PPC4XX_TLBLO_EX
;
2302 if (tlb
->prot
& PAGE_WRITE
) {
2303 ret
|= PPC4XX_TLBLO_WR
;
2308 void helper_4xx_tlbwe_hi(CPUPPCState
*env
, target_ulong entry
,
2311 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2312 CPUState
*cs
= CPU(cpu
);
2314 target_ulong page
, end
;
2316 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2318 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2319 tlb
= &env
->tlb
.tlbe
[entry
];
2320 /* Invalidate previous TLB (if it's valid) */
2321 if (tlb
->prot
& PAGE_VALID
) {
2322 end
= tlb
->EPN
+ tlb
->size
;
2323 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx
" end "
2324 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2325 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2326 tlb_flush_page(cs
, page
);
2329 tlb
->size
= booke_tlb_to_page_size((val
>> PPC4XX_TLBHI_SIZE_SHIFT
)
2330 & PPC4XX_TLBHI_SIZE_MASK
);
2331 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2332 * If this ever occurs, one should use the ppcemb target instead
2333 * of the ppc or ppc64 one
2335 if ((val
& PPC4XX_TLBHI_V
) && tlb
->size
< TARGET_PAGE_SIZE
) {
2336 cpu_abort(cs
, "TLB size " TARGET_FMT_lu
" < %u "
2337 "are not supported (%d)\n",
2338 tlb
->size
, TARGET_PAGE_SIZE
, (int)((val
>> 7) & 0x7));
2340 tlb
->EPN
= val
& ~(tlb
->size
- 1);
2341 if (val
& PPC4XX_TLBHI_V
) {
2342 tlb
->prot
|= PAGE_VALID
;
2343 if (val
& PPC4XX_TLBHI_E
) {
2344 /* XXX: TO BE FIXED */
2346 "Little-endian TLB entries are not supported by now\n");
2349 tlb
->prot
&= ~PAGE_VALID
;
2351 tlb
->PID
= env
->spr
[SPR_40x_PID
]; /* PID */
2352 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2353 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2354 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2355 tlb
->prot
& PAGE_READ
? 'r' : '-',
2356 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2357 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2358 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2359 /* Invalidate new TLB (if valid) */
2360 if (tlb
->prot
& PAGE_VALID
) {
2361 end
= tlb
->EPN
+ tlb
->size
;
2362 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx
" end "
2363 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2364 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2365 tlb_flush_page(cs
, page
);
2370 void helper_4xx_tlbwe_lo(CPUPPCState
*env
, target_ulong entry
,
2375 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2377 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2378 tlb
= &env
->tlb
.tlbe
[entry
];
2379 tlb
->attr
= val
& PPC4XX_TLBLO_ATTR_MASK
;
2380 tlb
->RPN
= val
& PPC4XX_TLBLO_RPN_MASK
;
2381 tlb
->prot
= PAGE_READ
;
2382 if (val
& PPC4XX_TLBLO_EX
) {
2383 tlb
->prot
|= PAGE_EXEC
;
2385 if (val
& PPC4XX_TLBLO_WR
) {
2386 tlb
->prot
|= PAGE_WRITE
;
2388 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2389 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2390 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2391 tlb
->prot
& PAGE_READ
? 'r' : '-',
2392 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2393 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2394 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2397 target_ulong
helper_4xx_tlbsx(CPUPPCState
*env
, target_ulong address
)
2399 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_40x_PID
]);
2402 /* PowerPC 440 TLB management */
2403 void helper_440_tlbwe(CPUPPCState
*env
, uint32_t word
, target_ulong entry
,
2406 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2408 target_ulong EPN
, RPN
, size
;
2411 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx
"\n",
2412 __func__
, word
, (int)entry
, value
);
2415 tlb
= &env
->tlb
.tlbe
[entry
];
2418 /* Just here to please gcc */
2420 EPN
= value
& 0xFFFFFC00;
2421 if ((tlb
->prot
& PAGE_VALID
) && EPN
!= tlb
->EPN
) {
2425 size
= booke_tlb_to_page_size((value
>> 4) & 0xF);
2426 if ((tlb
->prot
& PAGE_VALID
) && tlb
->size
< size
) {
2431 tlb
->attr
|= (value
>> 8) & 1;
2432 if (value
& 0x200) {
2433 tlb
->prot
|= PAGE_VALID
;
2435 if (tlb
->prot
& PAGE_VALID
) {
2436 tlb
->prot
&= ~PAGE_VALID
;
2440 tlb
->PID
= env
->spr
[SPR_440_MMUCR
] & 0x000000FF;
2441 if (do_flush_tlbs
) {
2442 tlb_flush(CPU(cpu
), 1);
2446 RPN
= value
& 0xFFFFFC0F;
2447 if ((tlb
->prot
& PAGE_VALID
) && tlb
->RPN
!= RPN
) {
2448 tlb_flush(CPU(cpu
), 1);
2453 tlb
->attr
= (tlb
->attr
& 0x1) | (value
& 0x0000FF00);
2454 tlb
->prot
= tlb
->prot
& PAGE_VALID
;
2456 tlb
->prot
|= PAGE_READ
<< 4;
2459 tlb
->prot
|= PAGE_WRITE
<< 4;
2462 tlb
->prot
|= PAGE_EXEC
<< 4;
2465 tlb
->prot
|= PAGE_READ
;
2468 tlb
->prot
|= PAGE_WRITE
;
2471 tlb
->prot
|= PAGE_EXEC
;
2477 target_ulong
helper_440_tlbre(CPUPPCState
*env
, uint32_t word
,
2485 tlb
= &env
->tlb
.tlbe
[entry
];
2488 /* Just here to please gcc */
2491 size
= booke_page_size_to_tlb(tlb
->size
);
2492 if (size
< 0 || size
> 0xF) {
2496 if (tlb
->attr
& 0x1) {
2499 if (tlb
->prot
& PAGE_VALID
) {
2502 env
->spr
[SPR_440_MMUCR
] &= ~0x000000FF;
2503 env
->spr
[SPR_440_MMUCR
] |= tlb
->PID
;
2509 ret
= tlb
->attr
& ~0x1;
2510 if (tlb
->prot
& (PAGE_READ
<< 4)) {
2513 if (tlb
->prot
& (PAGE_WRITE
<< 4)) {
2516 if (tlb
->prot
& (PAGE_EXEC
<< 4)) {
2519 if (tlb
->prot
& PAGE_READ
) {
2522 if (tlb
->prot
& PAGE_WRITE
) {
2525 if (tlb
->prot
& PAGE_EXEC
) {
2533 target_ulong
helper_440_tlbsx(CPUPPCState
*env
, target_ulong address
)
2535 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_440_MMUCR
] & 0xFF);
2538 /* PowerPC BookE 2.06 TLB management */
2540 static ppcmas_tlb_t
*booke206_cur_tlb(CPUPPCState
*env
)
2542 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2543 uint32_t tlbncfg
= 0;
2544 int esel
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ESEL_MASK
) >> MAS0_ESEL_SHIFT
;
2545 int ea
= (env
->spr
[SPR_BOOKE_MAS2
] & MAS2_EPN_MASK
);
2548 tlb
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2549 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlb
];
2551 if ((tlbncfg
& TLBnCFG_HES
) && (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_HES
)) {
2552 cpu_abort(CPU(cpu
), "we don't support HES yet\n");
2555 return booke206_get_tlbm(env
, tlb
, ea
, esel
);
2558 void helper_booke_setpid(CPUPPCState
*env
, uint32_t pidn
, target_ulong pid
)
2560 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2562 env
->spr
[pidn
] = pid
;
2563 /* changing PIDs mean we're in a different address space now */
2564 tlb_flush(CPU(cpu
), 1);
2567 void helper_booke206_tlbwe(CPUPPCState
*env
)
2569 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2570 uint32_t tlbncfg
, tlbn
;
2572 uint32_t size_tlb
, size_ps
;
2576 switch (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_WQ_MASK
) {
2577 case MAS0_WQ_ALWAYS
:
2578 /* good to go, write that entry */
2581 /* XXX check if reserved */
2586 case MAS0_WQ_CLR_RSRV
:
2587 /* XXX clear entry */
2590 /* no idea what to do */
2594 if (((env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ATSEL
) == MAS0_ATSEL_LRAT
) &&
2596 /* XXX we don't support direct LRAT setting yet */
2597 fprintf(stderr
, "cpu: don't support LRAT setting yet\n");
2601 tlbn
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2602 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlbn
];
2604 tlb
= booke206_cur_tlb(env
);
2607 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2608 POWERPC_EXCP_INVAL
|
2609 POWERPC_EXCP_INVAL_INVAL
);
2612 /* check that we support the targeted size */
2613 size_tlb
= (env
->spr
[SPR_BOOKE_MAS1
] & MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
2614 size_ps
= booke206_tlbnps(env
, tlbn
);
2615 if ((env
->spr
[SPR_BOOKE_MAS1
] & MAS1_VALID
) && (tlbncfg
& TLBnCFG_AVAIL
) &&
2616 !(size_ps
& (1 << size_tlb
))) {
2617 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2618 POWERPC_EXCP_INVAL
|
2619 POWERPC_EXCP_INVAL_INVAL
);
2623 cpu_abort(CPU(cpu
), "missing HV implementation\n");
2625 tlb
->mas7_3
= ((uint64_t)env
->spr
[SPR_BOOKE_MAS7
] << 32) |
2626 env
->spr
[SPR_BOOKE_MAS3
];
2627 tlb
->mas1
= env
->spr
[SPR_BOOKE_MAS1
];
2630 if (!(tlbncfg
& TLBnCFG_AVAIL
)) {
2631 /* force !AVAIL TLB entries to correct page size */
2632 tlb
->mas1
&= ~MAS1_TSIZE_MASK
;
2633 /* XXX can be configured in MMUCSR0 */
2634 tlb
->mas1
|= (tlbncfg
& TLBnCFG_MINSIZE
) >> 12;
2637 /* Make a mask from TLB size to discard invalid bits in EPN field */
2638 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2639 /* Add a mask for page attributes */
2640 mask
|= MAS2_ACM
| MAS2_VLE
| MAS2_W
| MAS2_I
| MAS2_M
| MAS2_G
| MAS2_E
;
2643 /* Executing a tlbwe instruction in 32-bit mode will set
2644 * bits 0:31 of the TLB EPN field to zero.
2649 tlb
->mas2
= env
->spr
[SPR_BOOKE_MAS2
] & mask
;
2651 if (!(tlbncfg
& TLBnCFG_IPROT
)) {
2652 /* no IPROT supported by TLB */
2653 tlb
->mas1
&= ~MAS1_IPROT
;
2656 if (booke206_tlb_to_page_size(env
, tlb
) == TARGET_PAGE_SIZE
) {
2657 tlb_flush_page(CPU(cpu
), tlb
->mas2
& MAS2_EPN_MASK
);
2659 tlb_flush(CPU(cpu
), 1);
2663 static inline void booke206_tlb_to_mas(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2665 int tlbn
= booke206_tlbm_to_tlbn(env
, tlb
);
2666 int way
= booke206_tlbm_to_way(env
, tlb
);
2668 env
->spr
[SPR_BOOKE_MAS0
] = tlbn
<< MAS0_TLBSEL_SHIFT
;
2669 env
->spr
[SPR_BOOKE_MAS0
] |= way
<< MAS0_ESEL_SHIFT
;
2670 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2672 env
->spr
[SPR_BOOKE_MAS1
] = tlb
->mas1
;
2673 env
->spr
[SPR_BOOKE_MAS2
] = tlb
->mas2
;
2674 env
->spr
[SPR_BOOKE_MAS3
] = tlb
->mas7_3
;
2675 env
->spr
[SPR_BOOKE_MAS7
] = tlb
->mas7_3
>> 32;
2678 void helper_booke206_tlbre(CPUPPCState
*env
)
2680 ppcmas_tlb_t
*tlb
= NULL
;
2682 tlb
= booke206_cur_tlb(env
);
2684 env
->spr
[SPR_BOOKE_MAS1
] = 0;
2686 booke206_tlb_to_mas(env
, tlb
);
2690 void helper_booke206_tlbsx(CPUPPCState
*env
, target_ulong address
)
2692 ppcmas_tlb_t
*tlb
= NULL
;
2697 spid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID_MASK
) >> MAS6_SPID_SHIFT
;
2698 sas
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
;
2700 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2701 int ways
= booke206_tlb_ways(env
, i
);
2703 for (j
= 0; j
< ways
; j
++) {
2704 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2710 if (ppcmas_tlb_check(env
, tlb
, &raddr
, address
, spid
)) {
2714 if (sas
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
2718 booke206_tlb_to_mas(env
, tlb
);
2723 /* no entry found, fill with defaults */
2724 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
2725 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
2726 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
2727 env
->spr
[SPR_BOOKE_MAS3
] = 0;
2728 env
->spr
[SPR_BOOKE_MAS7
] = 0;
2730 if (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
) {
2731 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
2734 env
->spr
[SPR_BOOKE_MAS1
] |= (env
->spr
[SPR_BOOKE_MAS6
] >> 16)
2737 /* next victim logic */
2738 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
2740 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
2741 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2744 static inline void booke206_invalidate_ea_tlb(CPUPPCState
*env
, int tlbn
,
2748 int ways
= booke206_tlb_ways(env
, tlbn
);
2751 for (i
= 0; i
< ways
; i
++) {
2752 ppcmas_tlb_t
*tlb
= booke206_get_tlbm(env
, tlbn
, ea
, i
);
2756 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2757 if (((tlb
->mas2
& MAS2_EPN_MASK
) == (ea
& mask
)) &&
2758 !(tlb
->mas1
& MAS1_IPROT
)) {
2759 tlb
->mas1
&= ~MAS1_VALID
;
2764 void helper_booke206_tlbivax(CPUPPCState
*env
, target_ulong address
)
2766 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2768 if (address
& 0x4) {
2769 /* flush all entries */
2770 if (address
& 0x8) {
2771 /* flush all of TLB1 */
2772 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB1
, 1);
2774 /* flush all of TLB0 */
2775 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB0
, 0);
2780 if (address
& 0x8) {
2781 /* flush TLB1 entries */
2782 booke206_invalidate_ea_tlb(env
, 1, address
);
2783 tlb_flush(CPU(cpu
), 1);
2785 /* flush TLB0 entries */
2786 booke206_invalidate_ea_tlb(env
, 0, address
);
2787 tlb_flush_page(CPU(cpu
), address
& MAS2_EPN_MASK
);
2791 void helper_booke206_tlbilx0(CPUPPCState
*env
, target_ulong address
)
2793 /* XXX missing LPID handling */
2794 booke206_flush_tlb(env
, -1, 1);
2797 void helper_booke206_tlbilx1(CPUPPCState
*env
, target_ulong address
)
2799 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2801 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2802 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
2805 /* XXX missing LPID handling */
2806 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2807 tlb_size
= booke206_tlb_size(env
, i
);
2808 for (j
= 0; j
< tlb_size
; j
++) {
2809 if (!(tlb
[j
].mas1
& MAS1_IPROT
) &&
2810 ((tlb
[j
].mas1
& MAS1_TID_MASK
) == tid
)) {
2811 tlb
[j
].mas1
&= ~MAS1_VALID
;
2814 tlb
+= booke206_tlb_size(env
, i
);
2816 tlb_flush(CPU(cpu
), 1);
2819 void helper_booke206_tlbilx3(CPUPPCState
*env
, target_ulong address
)
2821 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2824 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2825 int pid
= tid
>> MAS6_SPID_SHIFT
;
2826 int sgs
= env
->spr
[SPR_BOOKE_MAS5
] & MAS5_SGS
;
2827 int ind
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SIND
) ? MAS1_IND
: 0;
2828 /* XXX check for unsupported isize and raise an invalid opcode then */
2829 int size
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_ISIZE_MASK
;
2830 /* XXX implement MAV2 handling */
2833 /* XXX missing LPID handling */
2834 /* flush by pid and ea */
2835 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2836 int ways
= booke206_tlb_ways(env
, i
);
2838 for (j
= 0; j
< ways
; j
++) {
2839 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2843 if ((ppcmas_tlb_check(env
, tlb
, NULL
, address
, pid
) != 0) ||
2844 (tlb
->mas1
& MAS1_IPROT
) ||
2845 ((tlb
->mas1
& MAS1_IND
) != ind
) ||
2846 ((tlb
->mas8
& MAS8_TGS
) != sgs
)) {
2849 if (mav2
&& ((tlb
->mas1
& MAS1_TSIZE_MASK
) != size
)) {
2850 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2853 /* XXX e500mc doesn't match SAS, but other cores might */
2854 tlb
->mas1
&= ~MAS1_VALID
;
2857 tlb_flush(CPU(cpu
), 1);
2860 void helper_booke206_tlbflush(CPUPPCState
*env
, target_ulong type
)
2865 flags
|= BOOKE206_FLUSH_TLB1
;
2869 flags
|= BOOKE206_FLUSH_TLB0
;
2872 booke206_flush_tlb(env
, flags
, 1);
2876 /*****************************************************************************/
2878 /* try to fill the TLB and return an exception if error. If retaddr is
2879 NULL, it means that the function was called in C code (i.e. not
2880 from generated code or from helper.c) */
2881 /* XXX: fix it to restore all registers */
2882 void tlb_fill(CPUState
*cs
, target_ulong addr
, int is_write
, int mmu_idx
,
2885 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
2886 PowerPCCPUClass
*pcc
= POWERPC_CPU_GET_CLASS(cs
);
2887 CPUPPCState
*env
= &cpu
->env
;
2890 if (pcc
->handle_mmu_fault
) {
2891 ret
= pcc
->handle_mmu_fault(cpu
, addr
, is_write
, mmu_idx
);
2893 ret
= cpu_ppc_handle_mmu_fault(env
, addr
, is_write
, mmu_idx
);
2895 if (unlikely(ret
!= 0)) {
2896 if (likely(retaddr
)) {
2897 /* now we have a real cpu fault */
2898 cpu_restore_state(cs
, retaddr
);
2900 helper_raise_exception_err(env
, cs
->exception_index
, env
->error_code
);