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"
20 #include "qapi/error.h"
22 #include "exec/helper-proto.h"
23 #include "sysemu/kvm.h"
25 #include "mmu-hash64.h"
26 #include "mmu-hash32.h"
27 #include "exec/exec-all.h"
28 #include "exec/cpu_ldst.h"
33 //#define DEBUG_SOFTWARE_TLB
34 //#define DUMP_PAGE_TABLES
35 //#define FLUSH_ALL_TLBS
38 # define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0)
40 # define LOG_MMU_STATE(cpu) do { } while (0)
43 #ifdef DEBUG_SOFTWARE_TLB
44 # define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
46 # define LOG_SWTLB(...) do { } while (0)
50 # define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
52 # define LOG_BATS(...) do { } while (0)
55 /*****************************************************************************/
56 /* PowerPC MMU emulation */
58 /* Context used internally during MMU translations */
59 typedef struct mmu_ctx_t mmu_ctx_t
;
61 hwaddr raddr
; /* Real address */
62 hwaddr eaddr
; /* Effective address */
63 int prot
; /* Protection bits */
64 hwaddr hash
[2]; /* Pagetable hash values */
65 target_ulong ptem
; /* Virtual segment ID | API */
66 int key
; /* Access key */
67 int nx
; /* Non-execute area */
70 /* Common routines used by software and hardware TLBs emulation */
71 static inline int pte_is_valid(target_ulong pte0
)
73 return pte0
& 0x80000000 ? 1 : 0;
76 static inline void pte_invalidate(target_ulong
*pte0
)
81 #define PTE_PTEM_MASK 0x7FFFFFBF
82 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
84 static int pp_check(int key
, int pp
, int nx
)
88 /* Compute access rights */
111 access
= PAGE_READ
| PAGE_WRITE
;
122 static int check_prot(int prot
, int rw
, int access_type
)
126 if (access_type
== ACCESS_CODE
) {
127 if (prot
& PAGE_EXEC
) {
133 if (prot
& PAGE_WRITE
) {
139 if (prot
& PAGE_READ
) {
149 static inline int ppc6xx_tlb_pte_check(mmu_ctx_t
*ctx
, target_ulong pte0
,
150 target_ulong pte1
, int h
, int rw
, int type
)
152 target_ulong ptem
, mmask
;
153 int access
, ret
, pteh
, ptev
, pp
;
156 /* Check validity and table match */
157 ptev
= pte_is_valid(pte0
);
158 pteh
= (pte0
>> 6) & 1;
159 if (ptev
&& h
== pteh
) {
160 /* Check vsid & api */
161 ptem
= pte0
& PTE_PTEM_MASK
;
162 mmask
= PTE_CHECK_MASK
;
163 pp
= pte1
& 0x00000003;
164 if (ptem
== ctx
->ptem
) {
165 if (ctx
->raddr
!= (hwaddr
)-1ULL) {
166 /* all matches should have equal RPN, WIMG & PP */
167 if ((ctx
->raddr
& mmask
) != (pte1
& mmask
)) {
168 qemu_log_mask(CPU_LOG_MMU
, "Bad RPN/WIMG/PP\n");
172 /* Compute access rights */
173 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
174 /* Keep the matching PTE informations */
177 ret
= check_prot(ctx
->prot
, rw
, type
);
180 qemu_log_mask(CPU_LOG_MMU
, "PTE access granted !\n");
182 /* Access right violation */
183 qemu_log_mask(CPU_LOG_MMU
, "PTE access rejected\n");
191 static int pte_update_flags(mmu_ctx_t
*ctx
, target_ulong
*pte1p
,
196 /* Update page flags */
197 if (!(*pte1p
& 0x00000100)) {
198 /* Update accessed flag */
199 *pte1p
|= 0x00000100;
202 if (!(*pte1p
& 0x00000080)) {
203 if (rw
== 1 && ret
== 0) {
204 /* Update changed flag */
205 *pte1p
|= 0x00000080;
208 /* Force page fault for first write access */
209 ctx
->prot
&= ~PAGE_WRITE
;
216 /* Software driven TLB helpers */
217 static inline int ppc6xx_tlb_getnum(CPUPPCState
*env
, target_ulong eaddr
,
218 int way
, int is_code
)
222 /* Select TLB num in a way from address */
223 nr
= (eaddr
>> TARGET_PAGE_BITS
) & (env
->tlb_per_way
- 1);
225 nr
+= env
->tlb_per_way
* way
;
226 /* 6xx have separate TLBs for instructions and data */
227 if (is_code
&& env
->id_tlbs
== 1) {
234 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState
*env
)
236 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
240 /* LOG_SWTLB("Invalidate all TLBs\n"); */
241 /* Invalidate all defined software TLB */
243 if (env
->id_tlbs
== 1) {
246 for (nr
= 0; nr
< max
; nr
++) {
247 tlb
= &env
->tlb
.tlb6
[nr
];
248 pte_invalidate(&tlb
->pte0
);
250 tlb_flush(CPU(cpu
), 1);
253 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState
*env
,
255 int is_code
, int match_epn
)
257 #if !defined(FLUSH_ALL_TLBS)
258 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
262 /* Invalidate ITLB + DTLB, all ways */
263 for (way
= 0; way
< env
->nb_ways
; way
++) {
264 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
, is_code
);
265 tlb
= &env
->tlb
.tlb6
[nr
];
266 if (pte_is_valid(tlb
->pte0
) && (match_epn
== 0 || eaddr
== tlb
->EPN
)) {
267 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx
"\n", nr
,
269 pte_invalidate(&tlb
->pte0
);
270 tlb_flush_page(cs
, tlb
->EPN
);
274 /* XXX: PowerPC specification say this is valid as well */
275 ppc6xx_tlb_invalidate_all(env
);
279 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState
*env
,
280 target_ulong eaddr
, int is_code
)
282 ppc6xx_tlb_invalidate_virt2(env
, eaddr
, is_code
, 0);
285 static void ppc6xx_tlb_store(CPUPPCState
*env
, target_ulong EPN
, int way
,
286 int is_code
, target_ulong pte0
, target_ulong pte1
)
291 nr
= ppc6xx_tlb_getnum(env
, EPN
, way
, is_code
);
292 tlb
= &env
->tlb
.tlb6
[nr
];
293 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
294 " PTE1 " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
, EPN
, pte0
, pte1
);
295 /* Invalidate any pending reference in QEMU for this virtual address */
296 ppc6xx_tlb_invalidate_virt2(env
, EPN
, is_code
, 1);
300 /* Store last way for LRU mechanism */
304 static inline int ppc6xx_tlb_check(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
305 target_ulong eaddr
, int rw
, int access_type
)
312 ret
= -1; /* No TLB found */
313 for (way
= 0; way
< env
->nb_ways
; way
++) {
314 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
,
315 access_type
== ACCESS_CODE
? 1 : 0);
316 tlb
= &env
->tlb
.tlb6
[nr
];
317 /* This test "emulates" the PTE index match for hardware TLBs */
318 if ((eaddr
& TARGET_PAGE_MASK
) != tlb
->EPN
) {
319 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx
" " TARGET_FMT_lx
320 "] <> " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
,
321 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
322 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
, eaddr
);
325 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx
" <> " TARGET_FMT_lx
" "
326 TARGET_FMT_lx
" %c %c\n", nr
, env
->nb_tlb
,
327 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
328 tlb
->EPN
, eaddr
, tlb
->pte1
,
329 rw
? 'S' : 'L', access_type
== ACCESS_CODE
? 'I' : 'D');
330 switch (ppc6xx_tlb_pte_check(ctx
, tlb
->pte0
, tlb
->pte1
, 0, rw
, access_type
)) {
332 /* TLB inconsistency */
335 /* Access violation */
345 /* XXX: we should go on looping to check all TLBs consistency
346 * but we can speed-up the whole thing as the
347 * result would be undefined if TLBs are not consistent.
356 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx
" prot=%01x ret=%d\n",
357 ctx
->raddr
& TARGET_PAGE_MASK
, ctx
->prot
, ret
);
358 /* Update page flags */
359 pte_update_flags(ctx
, &env
->tlb
.tlb6
[best
].pte1
, ret
, rw
);
365 /* Perform BAT hit & translation */
366 static inline void bat_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
367 int *validp
, int *protp
, target_ulong
*BATu
,
373 bl
= (*BATu
& 0x00001FFC) << 15;
376 if (((msr_pr
== 0) && (*BATu
& 0x00000002)) ||
377 ((msr_pr
!= 0) && (*BATu
& 0x00000001))) {
379 pp
= *BATl
& 0x00000003;
381 prot
= PAGE_READ
| PAGE_EXEC
;
392 static int get_bat_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
393 target_ulong
virtual, int rw
, int type
)
395 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
396 target_ulong BEPIl
, BEPIu
, bl
;
400 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx
"\n", __func__
,
401 type
== ACCESS_CODE
? 'I' : 'D', virtual);
404 BATlt
= env
->IBAT
[1];
405 BATut
= env
->IBAT
[0];
408 BATlt
= env
->DBAT
[1];
409 BATut
= env
->DBAT
[0];
412 for (i
= 0; i
< env
->nb_BATs
; i
++) {
415 BEPIu
= *BATu
& 0xF0000000;
416 BEPIl
= *BATu
& 0x0FFE0000;
417 bat_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
418 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
419 " BATl " TARGET_FMT_lx
"\n", __func__
,
420 type
== ACCESS_CODE
? 'I' : 'D', i
, virtual, *BATu
, *BATl
);
421 if ((virtual & 0xF0000000) == BEPIu
&&
422 ((virtual & 0x0FFE0000) & ~bl
) == BEPIl
) {
425 /* Get physical address */
426 ctx
->raddr
= (*BATl
& 0xF0000000) |
427 ((virtual & 0x0FFE0000 & bl
) | (*BATl
& 0x0FFE0000)) |
428 (virtual & 0x0001F000);
429 /* Compute access rights */
431 ret
= check_prot(ctx
->prot
, rw
, type
);
433 LOG_BATS("BAT %d match: r " TARGET_FMT_plx
" prot=%c%c\n",
434 i
, ctx
->raddr
, ctx
->prot
& PAGE_READ
? 'R' : '-',
435 ctx
->prot
& PAGE_WRITE
? 'W' : '-');
442 #if defined(DEBUG_BATS)
443 if (qemu_log_enabled()) {
444 LOG_BATS("no BAT match for " TARGET_FMT_lx
":\n", virtual);
445 for (i
= 0; i
< 4; i
++) {
448 BEPIu
= *BATu
& 0xF0000000;
449 BEPIl
= *BATu
& 0x0FFE0000;
450 bl
= (*BATu
& 0x00001FFC) << 15;
451 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
452 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
453 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
454 __func__
, type
== ACCESS_CODE
? 'I' : 'D', i
, virtual,
455 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
464 /* Perform segment based translation */
465 static inline int get_segment_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
466 target_ulong eaddr
, int rw
, int type
)
470 int ds
, pr
, target_page_bits
;
472 target_ulong sr
, pgidx
;
477 sr
= env
->sr
[eaddr
>> 28];
478 ctx
->key
= (((sr
& 0x20000000) && (pr
!= 0)) ||
479 ((sr
& 0x40000000) && (pr
== 0))) ? 1 : 0;
480 ds
= sr
& 0x80000000 ? 1 : 0;
481 ctx
->nx
= sr
& 0x10000000 ? 1 : 0;
482 vsid
= sr
& 0x00FFFFFF;
483 target_page_bits
= TARGET_PAGE_BITS
;
484 qemu_log_mask(CPU_LOG_MMU
,
485 "Check segment v=" TARGET_FMT_lx
" %d " TARGET_FMT_lx
486 " nip=" TARGET_FMT_lx
" lr=" TARGET_FMT_lx
487 " ir=%d dr=%d pr=%d %d t=%d\n",
488 eaddr
, (int)(eaddr
>> 28), sr
, env
->nip
, env
->lr
, (int)msr_ir
,
489 (int)msr_dr
, pr
!= 0 ? 1 : 0, rw
, type
);
490 pgidx
= (eaddr
& ~SEGMENT_MASK_256M
) >> target_page_bits
;
492 ctx
->ptem
= (vsid
<< 7) | (pgidx
>> 10);
494 qemu_log_mask(CPU_LOG_MMU
,
495 "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx
"\n",
496 ctx
->key
, ds
, ctx
->nx
, vsid
);
499 /* Check if instruction fetch is allowed, if needed */
500 if (type
!= ACCESS_CODE
|| ctx
->nx
== 0) {
501 /* Page address translation */
502 qemu_log_mask(CPU_LOG_MMU
, "htab_base " TARGET_FMT_plx
503 " htab_mask " TARGET_FMT_plx
504 " hash " TARGET_FMT_plx
"\n",
505 env
->htab_base
, env
->htab_mask
, hash
);
507 ctx
->hash
[1] = ~hash
;
509 /* Initialize real address with an invalid value */
510 ctx
->raddr
= (hwaddr
)-1ULL;
511 /* Software TLB search */
512 ret
= ppc6xx_tlb_check(env
, ctx
, eaddr
, rw
, type
);
513 #if defined(DUMP_PAGE_TABLES)
514 if (qemu_log_mask(CPU_LOG_MMU
)) {
516 uint32_t a0
, a1
, a2
, a3
;
518 qemu_log("Page table: " TARGET_FMT_plx
" len " TARGET_FMT_plx
519 "\n", sdr
, mask
+ 0x80);
520 for (curaddr
= sdr
; curaddr
< (sdr
+ mask
+ 0x80);
522 a0
= ldl_phys(curaddr
);
523 a1
= ldl_phys(curaddr
+ 4);
524 a2
= ldl_phys(curaddr
+ 8);
525 a3
= ldl_phys(curaddr
+ 12);
526 if (a0
!= 0 || a1
!= 0 || a2
!= 0 || a3
!= 0) {
527 qemu_log(TARGET_FMT_plx
": %08x %08x %08x %08x\n",
528 curaddr
, a0
, a1
, a2
, a3
);
534 qemu_log_mask(CPU_LOG_MMU
, "No access allowed\n");
540 qemu_log_mask(CPU_LOG_MMU
, "direct store...\n");
541 /* Direct-store segment : absolutely *BUGGY* for now */
543 /* Direct-store implies a 32-bit MMU.
544 * Check the Segment Register's bus unit ID (BUID).
546 sr
= env
->sr
[eaddr
>> 28];
547 if ((sr
& 0x1FF00000) >> 20 == 0x07f) {
548 /* Memory-forced I/O controller interface access */
549 /* If T=1 and BUID=x'07F', the 601 performs a memory access
550 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
552 ctx
->raddr
= ((sr
& 0xF) << 28) | (eaddr
& 0x0FFFFFFF);
553 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
559 /* Integer load/store : only access allowed */
562 /* No code fetch is allowed in direct-store areas */
565 /* Floating point load/store */
568 /* lwarx, ldarx or srwcx. */
571 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
572 /* Should make the instruction do no-op.
573 * As it already do no-op, it's quite easy :-)
581 qemu_log_mask(CPU_LOG_MMU
, "ERROR: instruction should not need "
582 "address translation\n");
585 if ((rw
== 1 || ctx
->key
!= 1) && (rw
== 0 || ctx
->key
!= 0)) {
596 /* Generic TLB check function for embedded PowerPC implementations */
597 static int ppcemb_tlb_check(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
599 target_ulong address
, uint32_t pid
, int ext
,
604 /* Check valid flag */
605 if (!(tlb
->prot
& PAGE_VALID
)) {
608 mask
= ~(tlb
->size
- 1);
609 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx
" PID %u <=> " TARGET_FMT_lx
610 " " TARGET_FMT_lx
" %u %x\n", __func__
, i
, address
, pid
, tlb
->EPN
,
611 mask
, (uint32_t)tlb
->PID
, tlb
->prot
);
613 if (tlb
->PID
!= 0 && tlb
->PID
!= pid
) {
616 /* Check effective address */
617 if ((address
& mask
) != tlb
->EPN
) {
620 *raddrp
= (tlb
->RPN
& mask
) | (address
& ~mask
);
622 /* Extend the physical address to 36 bits */
623 *raddrp
|= (uint64_t)(tlb
->RPN
& 0xF) << 32;
629 /* Generic TLB search function for PowerPC embedded implementations */
630 static int ppcemb_tlb_search(CPUPPCState
*env
, target_ulong address
,
637 /* Default return value is no match */
639 for (i
= 0; i
< env
->nb_tlb
; i
++) {
640 tlb
= &env
->tlb
.tlbe
[i
];
641 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
, pid
, 0, i
) == 0) {
650 /* Helpers specific to PowerPC 40x implementations */
651 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState
*env
)
653 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
657 for (i
= 0; i
< env
->nb_tlb
; i
++) {
658 tlb
= &env
->tlb
.tlbe
[i
];
659 tlb
->prot
&= ~PAGE_VALID
;
661 tlb_flush(CPU(cpu
), 1);
664 static int mmu40x_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
665 target_ulong address
, int rw
,
670 int i
, ret
, zsel
, zpr
, pr
;
673 raddr
= (hwaddr
)-1ULL;
675 for (i
= 0; i
< env
->nb_tlb
; i
++) {
676 tlb
= &env
->tlb
.tlbe
[i
];
677 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
678 env
->spr
[SPR_40x_PID
], 0, i
) < 0) {
681 zsel
= (tlb
->attr
>> 4) & 0xF;
682 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (30 - (2 * zsel
))) & 0x3;
683 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
684 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
685 /* Check execute enable bit */
693 /* All accesses granted */
694 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
699 /* Raise Zone protection fault. */
700 env
->spr
[SPR_40x_ESR
] = 1 << 22;
708 /* Check from TLB entry */
709 ctx
->prot
= tlb
->prot
;
710 ret
= check_prot(ctx
->prot
, rw
, access_type
);
712 env
->spr
[SPR_40x_ESR
] = 0;
718 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
719 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
724 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
725 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
730 void store_40x_sler(CPUPPCState
*env
, uint32_t val
)
732 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
734 /* XXX: TO BE FIXED */
735 if (val
!= 0x00000000) {
736 cpu_abort(CPU(cpu
), "Little-endian regions are not supported by now\n");
738 env
->spr
[SPR_405_SLER
] = val
;
741 static inline int mmubooke_check_tlb(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
742 hwaddr
*raddr
, int *prot
,
743 target_ulong address
, int rw
,
744 int access_type
, int i
)
748 if (ppcemb_tlb_check(env
, tlb
, raddr
, address
,
749 env
->spr
[SPR_BOOKE_PID
],
750 !env
->nb_pids
, i
) >= 0) {
754 if (env
->spr
[SPR_BOOKE_PID1
] &&
755 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
756 env
->spr
[SPR_BOOKE_PID1
], 0, i
) >= 0) {
760 if (env
->spr
[SPR_BOOKE_PID2
] &&
761 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
762 env
->spr
[SPR_BOOKE_PID2
], 0, i
) >= 0) {
766 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
772 prot2
= tlb
->prot
& 0xF;
774 prot2
= (tlb
->prot
>> 4) & 0xF;
777 /* Check the address space */
778 if (access_type
== ACCESS_CODE
) {
779 if (msr_ir
!= (tlb
->attr
& 1)) {
780 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
785 if (prot2
& PAGE_EXEC
) {
786 LOG_SWTLB("%s: good TLB!\n", __func__
);
790 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
793 if (msr_dr
!= (tlb
->attr
& 1)) {
794 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
799 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
800 LOG_SWTLB("%s: found TLB!\n", __func__
);
804 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
811 static int mmubooke_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
812 target_ulong address
, int rw
,
820 raddr
= (hwaddr
)-1ULL;
821 for (i
= 0; i
< env
->nb_tlb
; i
++) {
822 tlb
= &env
->tlb
.tlbe
[i
];
823 ret
= mmubooke_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
, rw
,
832 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
833 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
836 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
837 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
843 static void booke206_flush_tlb(CPUPPCState
*env
, int flags
,
844 const int check_iprot
)
846 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
849 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
851 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
852 if (flags
& (1 << i
)) {
853 tlb_size
= booke206_tlb_size(env
, i
);
854 for (j
= 0; j
< tlb_size
; j
++) {
855 if (!check_iprot
|| !(tlb
[j
].mas1
& MAS1_IPROT
)) {
856 tlb
[j
].mas1
&= ~MAS1_VALID
;
860 tlb
+= booke206_tlb_size(env
, i
);
863 tlb_flush(CPU(cpu
), 1);
866 static hwaddr
booke206_tlb_to_page_size(CPUPPCState
*env
,
871 tlbm_size
= (tlb
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
873 return 1024ULL << tlbm_size
;
876 /* TLB check function for MAS based SoftTLBs */
877 static int ppcmas_tlb_check(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
878 hwaddr
*raddrp
, target_ulong address
,
885 /* In 32bit mode we can only address 32bit EAs */
886 address
= (uint32_t)address
;
889 /* Check valid flag */
890 if (!(tlb
->mas1
& MAS1_VALID
)) {
894 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
895 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx
" PID=0x%x MAS1=0x%x MAS2=0x%"
896 PRIx64
" mask=0x" TARGET_FMT_lx
" MAS7_3=0x%" PRIx64
" MAS8=%x\n",
897 __func__
, address
, pid
, tlb
->mas1
, tlb
->mas2
, mask
, tlb
->mas7_3
,
901 tlb_pid
= (tlb
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
;
902 if (tlb_pid
!= 0 && tlb_pid
!= pid
) {
906 /* Check effective address */
907 if ((address
& mask
) != (tlb
->mas2
& MAS2_EPN_MASK
)) {
912 *raddrp
= (tlb
->mas7_3
& mask
) | (address
& ~mask
);
918 static int mmubooke206_check_tlb(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
919 hwaddr
*raddr
, int *prot
,
920 target_ulong address
, int rw
,
926 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
,
927 env
->spr
[SPR_BOOKE_PID
]) >= 0) {
931 if (env
->spr
[SPR_BOOKE_PID1
] &&
932 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
933 env
->spr
[SPR_BOOKE_PID1
]) >= 0) {
937 if (env
->spr
[SPR_BOOKE_PID2
] &&
938 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
939 env
->spr
[SPR_BOOKE_PID2
]) >= 0) {
943 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
949 if (tlb
->mas7_3
& MAS3_UR
) {
952 if (tlb
->mas7_3
& MAS3_UW
) {
955 if (tlb
->mas7_3
& MAS3_UX
) {
959 if (tlb
->mas7_3
& MAS3_SR
) {
962 if (tlb
->mas7_3
& MAS3_SW
) {
965 if (tlb
->mas7_3
& MAS3_SX
) {
970 /* Check the address space and permissions */
971 if (access_type
== ACCESS_CODE
) {
972 if (msr_ir
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
973 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
978 if (prot2
& PAGE_EXEC
) {
979 LOG_SWTLB("%s: good TLB!\n", __func__
);
983 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
986 if (msr_dr
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
987 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
992 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
993 LOG_SWTLB("%s: found TLB!\n", __func__
);
997 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
1004 static int mmubooke206_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1005 target_ulong address
, int rw
,
1013 raddr
= (hwaddr
)-1ULL;
1015 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1016 int ways
= booke206_tlb_ways(env
, i
);
1018 for (j
= 0; j
< ways
; j
++) {
1019 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
1023 ret
= mmubooke206_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
,
1035 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
1036 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1039 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
1040 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
1046 static const char *book3e_tsize_to_str
[32] = {
1047 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1048 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1049 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1053 static void mmubooke_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1056 ppcemb_tlb_t
*entry
;
1059 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1060 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1064 cpu_fprintf(f
, "\nTLB:\n");
1065 cpu_fprintf(f
, "Effective Physical Size PID Prot "
1068 entry
= &env
->tlb
.tlbe
[0];
1069 for (i
= 0; i
< env
->nb_tlb
; i
++, entry
++) {
1072 uint64_t size
= (uint64_t)entry
->size
;
1075 /* Check valid flag */
1076 if (!(entry
->prot
& PAGE_VALID
)) {
1080 mask
= ~(entry
->size
- 1);
1081 ea
= entry
->EPN
& mask
;
1082 pa
= entry
->RPN
& mask
;
1083 /* Extend the physical address to 36 bits */
1084 pa
|= (hwaddr
)(entry
->RPN
& 0xF) << 32;
1087 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"M", size
/ 1024);
1089 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"k", size
);
1091 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %s %-5u %08x %08x\n",
1092 (uint64_t)ea
, (uint64_t)pa
, size_buf
, (uint32_t)entry
->PID
,
1093 entry
->prot
, entry
->attr
);
1098 static void mmubooke206_dump_one_tlb(FILE *f
, fprintf_function cpu_fprintf
,
1099 CPUPPCState
*env
, int tlbn
, int offset
,
1102 ppcmas_tlb_t
*entry
;
1105 cpu_fprintf(f
, "\nTLB%d:\n", tlbn
);
1106 cpu_fprintf(f
, "Effective Physical Size TID TS SRWX"
1107 " URWX WIMGE U0123\n");
1109 entry
= &env
->tlb
.tlbm
[offset
];
1110 for (i
= 0; i
< tlbsize
; i
++, entry
++) {
1111 hwaddr ea
, pa
, size
;
1114 if (!(entry
->mas1
& MAS1_VALID
)) {
1118 tsize
= (entry
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1119 size
= 1024ULL << tsize
;
1120 ea
= entry
->mas2
& ~(size
- 1);
1121 pa
= entry
->mas7_3
& ~(size
- 1);
1123 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %4s %-5u %1u S%c%c%c"
1124 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1125 (uint64_t)ea
, (uint64_t)pa
,
1126 book3e_tsize_to_str
[tsize
],
1127 (entry
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
,
1128 (entry
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
,
1129 entry
->mas7_3
& MAS3_SR
? 'R' : '-',
1130 entry
->mas7_3
& MAS3_SW
? 'W' : '-',
1131 entry
->mas7_3
& MAS3_SX
? 'X' : '-',
1132 entry
->mas7_3
& MAS3_UR
? 'R' : '-',
1133 entry
->mas7_3
& MAS3_UW
? 'W' : '-',
1134 entry
->mas7_3
& MAS3_UX
? 'X' : '-',
1135 entry
->mas2
& MAS2_W
? 'W' : '-',
1136 entry
->mas2
& MAS2_I
? 'I' : '-',
1137 entry
->mas2
& MAS2_M
? 'M' : '-',
1138 entry
->mas2
& MAS2_G
? 'G' : '-',
1139 entry
->mas2
& MAS2_E
? 'E' : '-',
1140 entry
->mas7_3
& MAS3_U0
? '0' : '-',
1141 entry
->mas7_3
& MAS3_U1
? '1' : '-',
1142 entry
->mas7_3
& MAS3_U2
? '2' : '-',
1143 entry
->mas7_3
& MAS3_U3
? '3' : '-');
1147 static void mmubooke206_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1153 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1154 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1158 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1159 int size
= booke206_tlb_size(env
, i
);
1165 mmubooke206_dump_one_tlb(f
, cpu_fprintf
, env
, i
, offset
, size
);
1170 static void mmu6xx_dump_BATs(FILE *f
, fprintf_function cpu_fprintf
,
1171 CPUPPCState
*env
, int type
)
1173 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
1174 target_ulong BEPIl
, BEPIu
, bl
;
1179 BATlt
= env
->IBAT
[1];
1180 BATut
= env
->IBAT
[0];
1183 BATlt
= env
->DBAT
[1];
1184 BATut
= env
->DBAT
[0];
1188 for (i
= 0; i
< env
->nb_BATs
; i
++) {
1191 BEPIu
= *BATu
& 0xF0000000;
1192 BEPIl
= *BATu
& 0x0FFE0000;
1193 bl
= (*BATu
& 0x00001FFC) << 15;
1194 cpu_fprintf(f
, "%s BAT%d BATu " TARGET_FMT_lx
1195 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
1196 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
1197 type
== ACCESS_CODE
? "code" : "data", i
,
1198 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
1202 static void mmu6xx_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1207 int type
, way
, entry
, i
;
1209 cpu_fprintf(f
, "HTAB base = 0x%"HWADDR_PRIx
"\n", env
->htab_base
);
1210 cpu_fprintf(f
, "HTAB mask = 0x%"HWADDR_PRIx
"\n", env
->htab_mask
);
1212 cpu_fprintf(f
, "\nSegment registers:\n");
1213 for (i
= 0; i
< 32; i
++) {
1215 if (sr
& 0x80000000) {
1216 cpu_fprintf(f
, "%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1217 "CNTLR_SPEC=0x%05x\n", i
,
1218 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1219 sr
& 0x20000000 ? 1 : 0, (uint32_t)((sr
>> 20) & 0x1FF),
1220 (uint32_t)(sr
& 0xFFFFF));
1222 cpu_fprintf(f
, "%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i
,
1223 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1224 sr
& 0x20000000 ? 1 : 0, sr
& 0x10000000 ? 1 : 0,
1225 (uint32_t)(sr
& 0x00FFFFFF));
1229 cpu_fprintf(f
, "\nBATs:\n");
1230 mmu6xx_dump_BATs(f
, cpu_fprintf
, env
, ACCESS_INT
);
1231 mmu6xx_dump_BATs(f
, cpu_fprintf
, env
, ACCESS_CODE
);
1233 if (env
->id_tlbs
!= 1) {
1234 cpu_fprintf(f
, "ERROR: 6xx MMU should have separated TLB"
1235 " for code and data\n");
1238 cpu_fprintf(f
, "\nTLBs [EPN EPN + SIZE]\n");
1240 for (type
= 0; type
< 2; type
++) {
1241 for (way
= 0; way
< env
->nb_ways
; way
++) {
1242 for (entry
= env
->nb_tlb
* type
+ env
->tlb_per_way
* way
;
1243 entry
< (env
->nb_tlb
* type
+ env
->tlb_per_way
* (way
+ 1));
1246 tlb
= &env
->tlb
.tlb6
[entry
];
1247 cpu_fprintf(f
, "%s TLB %02d/%02d way:%d %s ["
1248 TARGET_FMT_lx
" " TARGET_FMT_lx
"]\n",
1249 type
? "code" : "data", entry
% env
->nb_tlb
,
1251 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
1252 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
);
1258 void dump_mmu(FILE *f
, fprintf_function cpu_fprintf
, CPUPPCState
*env
)
1260 switch (env
->mmu_model
) {
1261 case POWERPC_MMU_BOOKE
:
1262 mmubooke_dump_mmu(f
, cpu_fprintf
, env
);
1264 case POWERPC_MMU_BOOKE206
:
1265 mmubooke206_dump_mmu(f
, cpu_fprintf
, env
);
1267 case POWERPC_MMU_SOFT_6xx
:
1268 case POWERPC_MMU_SOFT_74xx
:
1269 mmu6xx_dump_mmu(f
, cpu_fprintf
, env
);
1271 #if defined(TARGET_PPC64)
1272 case POWERPC_MMU_64B
:
1273 case POWERPC_MMU_2_03
:
1274 case POWERPC_MMU_2_06
:
1275 case POWERPC_MMU_2_06a
:
1276 case POWERPC_MMU_2_07
:
1277 case POWERPC_MMU_2_07a
:
1278 dump_slb(f
, cpu_fprintf
, ppc_env_get_cpu(env
));
1282 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented\n", __func__
);
1286 static inline int check_physical(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1287 target_ulong eaddr
, int rw
)
1292 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1294 switch (env
->mmu_model
) {
1295 case POWERPC_MMU_SOFT_6xx
:
1296 case POWERPC_MMU_SOFT_74xx
:
1297 case POWERPC_MMU_SOFT_4xx
:
1298 case POWERPC_MMU_REAL
:
1299 case POWERPC_MMU_BOOKE
:
1300 ctx
->prot
|= PAGE_WRITE
;
1303 case POWERPC_MMU_SOFT_4xx_Z
:
1304 if (unlikely(msr_pe
!= 0)) {
1305 /* 403 family add some particular protections,
1306 * using PBL/PBU registers for accesses with no translation.
1309 /* Check PLB validity */
1310 (env
->pb
[0] < env
->pb
[1] &&
1311 /* and address in plb area */
1312 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1313 (env
->pb
[2] < env
->pb
[3] &&
1314 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1315 if (in_plb
^ msr_px
) {
1316 /* Access in protected area */
1318 /* Access is not allowed */
1322 /* Read-write access is allowed */
1323 ctx
->prot
|= PAGE_WRITE
;
1329 /* Caller's checks mean we should never get here for other models */
1337 static int get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1338 target_ulong eaddr
, int rw
, int access_type
)
1340 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1342 bool real_mode
= (access_type
== ACCESS_CODE
&& msr_ir
== 0)
1343 || (access_type
!= ACCESS_CODE
&& msr_dr
== 0);
1346 qemu_log("%s\n", __func__
);
1349 switch (env
->mmu_model
) {
1350 case POWERPC_MMU_SOFT_6xx
:
1351 case POWERPC_MMU_SOFT_74xx
:
1353 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1355 /* Try to find a BAT */
1356 if (env
->nb_BATs
!= 0) {
1357 ret
= get_bat_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1360 /* We didn't match any BAT entry or don't have BATs */
1361 ret
= get_segment_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1366 case POWERPC_MMU_SOFT_4xx
:
1367 case POWERPC_MMU_SOFT_4xx_Z
:
1369 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1371 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1375 case POWERPC_MMU_BOOKE
:
1376 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1379 case POWERPC_MMU_BOOKE206
:
1380 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1383 case POWERPC_MMU_MPC8xx
:
1385 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1387 case POWERPC_MMU_REAL
:
1389 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1391 cpu_abort(CPU(cpu
), "PowerPC in real mode do not do any translation\n");
1395 cpu_abort(CPU(cpu
), "Unknown or invalid MMU model\n");
1399 qemu_log("%s address " TARGET_FMT_lx
" => %d " TARGET_FMT_plx
"\n",
1400 __func__
, eaddr
, ret
, ctx
->raddr
);
1406 hwaddr
ppc_cpu_get_phys_page_debug(CPUState
*cs
, vaddr addr
)
1408 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
1409 CPUPPCState
*env
= &cpu
->env
;
1412 switch (env
->mmu_model
) {
1413 #if defined(TARGET_PPC64)
1414 case POWERPC_MMU_64B
:
1415 case POWERPC_MMU_2_03
:
1416 case POWERPC_MMU_2_06
:
1417 case POWERPC_MMU_2_06a
:
1418 case POWERPC_MMU_2_07
:
1419 case POWERPC_MMU_2_07a
:
1420 return ppc_hash64_get_phys_page_debug(cpu
, addr
);
1423 case POWERPC_MMU_32B
:
1424 case POWERPC_MMU_601
:
1425 return ppc_hash32_get_phys_page_debug(cpu
, addr
);
1431 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0)) {
1433 /* Some MMUs have separate TLBs for code and data. If we only try an
1434 * ACCESS_INT, we may not be able to read instructions mapped by code
1435 * TLBs, so we also try a ACCESS_CODE.
1437 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0,
1438 ACCESS_CODE
) != 0)) {
1443 return ctx
.raddr
& TARGET_PAGE_MASK
;
1446 static void booke206_update_mas_tlb_miss(CPUPPCState
*env
, target_ulong address
,
1449 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
1450 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
1451 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
1452 env
->spr
[SPR_BOOKE_MAS3
] = 0;
1453 env
->spr
[SPR_BOOKE_MAS6
] = 0;
1454 env
->spr
[SPR_BOOKE_MAS7
] = 0;
1457 if (((rw
== 2) && msr_ir
) || ((rw
!= 2) && msr_dr
)) {
1458 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
1459 env
->spr
[SPR_BOOKE_MAS6
] |= MAS6_SAS
;
1462 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_VALID
;
1463 env
->spr
[SPR_BOOKE_MAS2
] |= address
& MAS2_EPN_MASK
;
1465 switch (env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TIDSELD_PIDZ
) {
1466 case MAS4_TIDSELD_PID0
:
1467 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID
] << MAS1_TID_SHIFT
;
1469 case MAS4_TIDSELD_PID1
:
1470 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID1
] << MAS1_TID_SHIFT
;
1472 case MAS4_TIDSELD_PID2
:
1473 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID2
] << MAS1_TID_SHIFT
;
1477 env
->spr
[SPR_BOOKE_MAS6
] |= env
->spr
[SPR_BOOKE_PID
] << 16;
1479 /* next victim logic */
1480 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
1482 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
1483 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
1486 /* Perform address translation */
1487 static int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
,
1488 int rw
, int mmu_idx
)
1490 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1491 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
1499 access_type
= ACCESS_CODE
;
1502 access_type
= env
->access_type
;
1504 ret
= get_physical_address(env
, &ctx
, address
, rw
, access_type
);
1506 tlb_set_page(cs
, address
& TARGET_PAGE_MASK
,
1507 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1508 mmu_idx
, TARGET_PAGE_SIZE
);
1510 } else if (ret
< 0) {
1512 if (access_type
== ACCESS_CODE
) {
1515 /* No matches in page tables or TLB */
1516 switch (env
->mmu_model
) {
1517 case POWERPC_MMU_SOFT_6xx
:
1518 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1519 env
->error_code
= 1 << 18;
1520 env
->spr
[SPR_IMISS
] = address
;
1521 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1523 case POWERPC_MMU_SOFT_74xx
:
1524 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1526 case POWERPC_MMU_SOFT_4xx
:
1527 case POWERPC_MMU_SOFT_4xx_Z
:
1528 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1529 env
->error_code
= 0;
1530 env
->spr
[SPR_40x_DEAR
] = address
;
1531 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1533 case POWERPC_MMU_BOOKE206
:
1534 booke206_update_mas_tlb_miss(env
, address
, rw
);
1536 case POWERPC_MMU_BOOKE
:
1537 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1538 env
->error_code
= 0;
1539 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1541 case POWERPC_MMU_MPC8xx
:
1543 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1545 case POWERPC_MMU_REAL
:
1546 cpu_abort(cs
, "PowerPC in real mode should never raise "
1547 "any MMU exceptions\n");
1550 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1555 /* Access rights violation */
1556 cs
->exception_index
= POWERPC_EXCP_ISI
;
1557 env
->error_code
= 0x08000000;
1560 /* No execute protection violation */
1561 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1562 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1563 env
->spr
[SPR_BOOKE_ESR
] = 0x00000000;
1565 cs
->exception_index
= POWERPC_EXCP_ISI
;
1566 env
->error_code
= 0x10000000;
1569 /* Direct store exception */
1570 /* No code fetch is allowed in direct-store areas */
1571 cs
->exception_index
= POWERPC_EXCP_ISI
;
1572 env
->error_code
= 0x10000000;
1578 /* No matches in page tables or TLB */
1579 switch (env
->mmu_model
) {
1580 case POWERPC_MMU_SOFT_6xx
:
1582 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1583 env
->error_code
= 1 << 16;
1585 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1586 env
->error_code
= 0;
1588 env
->spr
[SPR_DMISS
] = address
;
1589 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1591 env
->error_code
|= ctx
.key
<< 19;
1592 env
->spr
[SPR_HASH1
] = env
->htab_base
+
1593 get_pteg_offset32(cpu
, ctx
.hash
[0]);
1594 env
->spr
[SPR_HASH2
] = env
->htab_base
+
1595 get_pteg_offset32(cpu
, ctx
.hash
[1]);
1597 case POWERPC_MMU_SOFT_74xx
:
1599 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1601 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1604 /* Implement LRU algorithm */
1605 env
->error_code
= ctx
.key
<< 19;
1606 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1607 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1608 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1610 case POWERPC_MMU_SOFT_4xx
:
1611 case POWERPC_MMU_SOFT_4xx_Z
:
1612 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1613 env
->error_code
= 0;
1614 env
->spr
[SPR_40x_DEAR
] = address
;
1616 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1618 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1621 case POWERPC_MMU_MPC8xx
:
1623 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1625 case POWERPC_MMU_BOOKE206
:
1626 booke206_update_mas_tlb_miss(env
, address
, rw
);
1628 case POWERPC_MMU_BOOKE
:
1629 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1630 env
->error_code
= 0;
1631 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1632 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1634 case POWERPC_MMU_REAL
:
1635 cpu_abort(cs
, "PowerPC in real mode should never raise "
1636 "any MMU exceptions\n");
1639 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1644 /* Access rights violation */
1645 cs
->exception_index
= POWERPC_EXCP_DSI
;
1646 env
->error_code
= 0;
1647 if (env
->mmu_model
== POWERPC_MMU_SOFT_4xx
1648 || env
->mmu_model
== POWERPC_MMU_SOFT_4xx_Z
) {
1649 env
->spr
[SPR_40x_DEAR
] = address
;
1651 env
->spr
[SPR_40x_ESR
] |= 0x00800000;
1653 } else if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1654 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1655 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1656 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1658 env
->spr
[SPR_DAR
] = address
;
1660 env
->spr
[SPR_DSISR
] = 0x0A000000;
1662 env
->spr
[SPR_DSISR
] = 0x08000000;
1667 /* Direct store exception */
1668 switch (access_type
) {
1670 /* Floating point load/store */
1671 cs
->exception_index
= POWERPC_EXCP_ALIGN
;
1672 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1673 env
->spr
[SPR_DAR
] = address
;
1676 /* lwarx, ldarx or stwcx. */
1677 cs
->exception_index
= POWERPC_EXCP_DSI
;
1678 env
->error_code
= 0;
1679 env
->spr
[SPR_DAR
] = address
;
1681 env
->spr
[SPR_DSISR
] = 0x06000000;
1683 env
->spr
[SPR_DSISR
] = 0x04000000;
1687 /* eciwx or ecowx */
1688 cs
->exception_index
= POWERPC_EXCP_DSI
;
1689 env
->error_code
= 0;
1690 env
->spr
[SPR_DAR
] = address
;
1692 env
->spr
[SPR_DSISR
] = 0x06100000;
1694 env
->spr
[SPR_DSISR
] = 0x04100000;
1698 printf("DSI: invalid exception (%d)\n", ret
);
1699 cs
->exception_index
= POWERPC_EXCP_PROGRAM
;
1701 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1702 env
->spr
[SPR_DAR
] = address
;
1709 printf("%s: set exception to %d %02x\n", __func__
,
1710 cs
->exception
, env
->error_code
);
1718 /*****************************************************************************/
1719 /* BATs management */
1720 #if !defined(FLUSH_ALL_TLBS)
1721 static inline void do_invalidate_BAT(CPUPPCState
*env
, target_ulong BATu
,
1724 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1725 target_ulong base
, end
, page
;
1727 base
= BATu
& ~0x0001FFFF;
1728 end
= base
+ mask
+ 0x00020000;
1729 LOG_BATS("Flush BAT from " TARGET_FMT_lx
" to " TARGET_FMT_lx
" ("
1730 TARGET_FMT_lx
")\n", base
, end
, mask
);
1731 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
1732 tlb_flush_page(cs
, page
);
1734 LOG_BATS("Flush done\n");
1738 static inline void dump_store_bat(CPUPPCState
*env
, char ID
, int ul
, int nr
,
1741 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx
" (" TARGET_FMT_lx
")\n", ID
,
1742 nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1745 void helper_store_ibatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1749 dump_store_bat(env
, 'I', 0, nr
, value
);
1750 if (env
->IBAT
[0][nr
] != value
) {
1751 mask
= (value
<< 15) & 0x0FFE0000UL
;
1752 #if !defined(FLUSH_ALL_TLBS)
1753 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1755 /* When storing valid upper BAT, mask BEPI and BRPN
1756 * and invalidate all TLBs covered by this BAT
1758 mask
= (value
<< 15) & 0x0FFE0000UL
;
1759 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1760 (value
& ~0x0001FFFFUL
& ~mask
);
1761 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1762 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1763 #if !defined(FLUSH_ALL_TLBS)
1764 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1771 void helper_store_ibatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1773 dump_store_bat(env
, 'I', 1, nr
, value
);
1774 env
->IBAT
[1][nr
] = value
;
1777 void helper_store_dbatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1781 dump_store_bat(env
, 'D', 0, nr
, value
);
1782 if (env
->DBAT
[0][nr
] != value
) {
1783 /* When storing valid upper BAT, mask BEPI and BRPN
1784 * and invalidate all TLBs covered by this BAT
1786 mask
= (value
<< 15) & 0x0FFE0000UL
;
1787 #if !defined(FLUSH_ALL_TLBS)
1788 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1790 mask
= (value
<< 15) & 0x0FFE0000UL
;
1791 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1792 (value
& ~0x0001FFFFUL
& ~mask
);
1793 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1794 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1795 #if !defined(FLUSH_ALL_TLBS)
1796 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1803 void helper_store_dbatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1805 dump_store_bat(env
, 'D', 1, nr
, value
);
1806 env
->DBAT
[1][nr
] = value
;
1809 void helper_store_601_batu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1812 #if defined(FLUSH_ALL_TLBS)
1816 dump_store_bat(env
, 'I', 0, nr
, value
);
1817 if (env
->IBAT
[0][nr
] != value
) {
1818 #if defined(FLUSH_ALL_TLBS)
1821 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1822 if (env
->IBAT
[1][nr
] & 0x40) {
1823 /* Invalidate BAT only if it is valid */
1824 #if !defined(FLUSH_ALL_TLBS)
1825 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1830 /* When storing valid upper BAT, mask BEPI and BRPN
1831 * and invalidate all TLBs covered by this BAT
1833 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1834 (value
& ~0x0001FFFFUL
& ~mask
);
1835 env
->DBAT
[0][nr
] = env
->IBAT
[0][nr
];
1836 if (env
->IBAT
[1][nr
] & 0x40) {
1837 #if !defined(FLUSH_ALL_TLBS)
1838 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1843 #if defined(FLUSH_ALL_TLBS)
1851 void helper_store_601_batl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1853 #if !defined(FLUSH_ALL_TLBS)
1859 dump_store_bat(env
, 'I', 1, nr
, value
);
1860 if (env
->IBAT
[1][nr
] != value
) {
1861 #if defined(FLUSH_ALL_TLBS)
1864 if (env
->IBAT
[1][nr
] & 0x40) {
1865 #if !defined(FLUSH_ALL_TLBS)
1866 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1867 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1873 #if !defined(FLUSH_ALL_TLBS)
1874 mask
= (value
<< 17) & 0x0FFE0000UL
;
1875 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1880 env
->IBAT
[1][nr
] = value
;
1881 env
->DBAT
[1][nr
] = value
;
1882 #if defined(FLUSH_ALL_TLBS)
1890 /*****************************************************************************/
1891 /* TLB management */
1892 void ppc_tlb_invalidate_all(CPUPPCState
*env
)
1894 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1896 switch (env
->mmu_model
) {
1897 case POWERPC_MMU_SOFT_6xx
:
1898 case POWERPC_MMU_SOFT_74xx
:
1899 ppc6xx_tlb_invalidate_all(env
);
1901 case POWERPC_MMU_SOFT_4xx
:
1902 case POWERPC_MMU_SOFT_4xx_Z
:
1903 ppc4xx_tlb_invalidate_all(env
);
1905 case POWERPC_MMU_REAL
:
1906 cpu_abort(CPU(cpu
), "No TLB for PowerPC 4xx in real mode\n");
1908 case POWERPC_MMU_MPC8xx
:
1910 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1912 case POWERPC_MMU_BOOKE
:
1913 tlb_flush(CPU(cpu
), 1);
1915 case POWERPC_MMU_BOOKE206
:
1916 booke206_flush_tlb(env
, -1, 0);
1918 case POWERPC_MMU_32B
:
1919 case POWERPC_MMU_601
:
1920 #if defined(TARGET_PPC64)
1921 case POWERPC_MMU_64B
:
1922 case POWERPC_MMU_2_03
:
1923 case POWERPC_MMU_2_06
:
1924 case POWERPC_MMU_2_06a
:
1925 case POWERPC_MMU_2_07
:
1926 case POWERPC_MMU_2_07a
:
1927 #endif /* defined(TARGET_PPC64) */
1928 tlb_flush(CPU(cpu
), 1);
1932 cpu_abort(CPU(cpu
), "Unknown MMU model\n");
1937 void ppc_tlb_invalidate_one(CPUPPCState
*env
, target_ulong addr
)
1939 #if !defined(FLUSH_ALL_TLBS)
1940 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1943 addr
&= TARGET_PAGE_MASK
;
1944 switch (env
->mmu_model
) {
1945 case POWERPC_MMU_SOFT_6xx
:
1946 case POWERPC_MMU_SOFT_74xx
:
1947 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
1948 if (env
->id_tlbs
== 1) {
1949 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
1952 case POWERPC_MMU_32B
:
1953 case POWERPC_MMU_601
:
1954 /* tlbie invalidate TLBs for all segments */
1955 addr
&= ~((target_ulong
)-1ULL << 28);
1957 /* XXX: this case should be optimized,
1958 * giving a mask to tlb_flush_page
1960 tlb_flush_page(cs
, addr
| (0x0 << 28));
1961 tlb_flush_page(cs
, addr
| (0x1 << 28));
1962 tlb_flush_page(cs
, addr
| (0x2 << 28));
1963 tlb_flush_page(cs
, addr
| (0x3 << 28));
1964 tlb_flush_page(cs
, addr
| (0x4 << 28));
1965 tlb_flush_page(cs
, addr
| (0x5 << 28));
1966 tlb_flush_page(cs
, addr
| (0x6 << 28));
1967 tlb_flush_page(cs
, addr
| (0x7 << 28));
1968 tlb_flush_page(cs
, addr
| (0x8 << 28));
1969 tlb_flush_page(cs
, addr
| (0x9 << 28));
1970 tlb_flush_page(cs
, addr
| (0xA << 28));
1971 tlb_flush_page(cs
, addr
| (0xB << 28));
1972 tlb_flush_page(cs
, addr
| (0xC << 28));
1973 tlb_flush_page(cs
, addr
| (0xD << 28));
1974 tlb_flush_page(cs
, addr
| (0xE << 28));
1975 tlb_flush_page(cs
, addr
| (0xF << 28));
1977 #if defined(TARGET_PPC64)
1978 case POWERPC_MMU_64B
:
1979 case POWERPC_MMU_2_03
:
1980 case POWERPC_MMU_2_06
:
1981 case POWERPC_MMU_2_06a
:
1982 case POWERPC_MMU_2_07
:
1983 case POWERPC_MMU_2_07a
:
1984 /* tlbie invalidate TLBs for all segments */
1985 /* XXX: given the fact that there are too many segments to invalidate,
1986 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
1987 * we just invalidate all TLBs
1989 tlb_flush(CPU(cpu
), 1);
1991 #endif /* defined(TARGET_PPC64) */
1993 /* Should never reach here with other MMU models */
1997 ppc_tlb_invalidate_all(env
);
2001 /*****************************************************************************/
2002 /* Special registers manipulation */
2003 void ppc_store_sdr1(CPUPPCState
*env
, target_ulong value
)
2005 qemu_log_mask(CPU_LOG_MMU
, "%s: " TARGET_FMT_lx
"\n", __func__
, value
);
2006 assert(!env
->external_htab
);
2007 env
->spr
[SPR_SDR1
] = value
;
2008 #if defined(TARGET_PPC64)
2009 if (env
->mmu_model
& POWERPC_MMU_64
) {
2010 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2011 Error
*local_err
= NULL
;
2013 ppc_hash64_set_sdr1(cpu
, value
, &local_err
);
2015 error_report_err(local_err
);
2016 error_free(local_err
);
2019 #endif /* defined(TARGET_PPC64) */
2021 /* FIXME: Should check for valid HTABMASK values */
2022 env
->htab_mask
= ((value
& SDR_32_HTABMASK
) << 16) | 0xFFFF;
2023 env
->htab_base
= value
& SDR_32_HTABORG
;
2027 /* Segment registers load and store */
2028 target_ulong
helper_load_sr(CPUPPCState
*env
, target_ulong sr_num
)
2030 #if defined(TARGET_PPC64)
2031 if (env
->mmu_model
& POWERPC_MMU_64
) {
2036 return env
->sr
[sr_num
];
2039 void helper_store_sr(CPUPPCState
*env
, target_ulong srnum
, target_ulong value
)
2041 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2043 qemu_log_mask(CPU_LOG_MMU
,
2044 "%s: reg=%d " TARGET_FMT_lx
" " TARGET_FMT_lx
"\n", __func__
,
2045 (int)srnum
, value
, env
->sr
[srnum
]);
2046 #if defined(TARGET_PPC64)
2047 if (env
->mmu_model
& POWERPC_MMU_64
) {
2048 uint64_t esid
, vsid
;
2051 esid
= ((uint64_t)(srnum
& 0xf) << 28) | SLB_ESID_V
;
2054 vsid
= (value
& 0xfffffff) << 12;
2056 vsid
|= ((value
>> 27) & 0xf) << 8;
2058 ppc_store_slb(cpu
, srnum
, esid
, vsid
);
2061 if (env
->sr
[srnum
] != value
) {
2062 env
->sr
[srnum
] = value
;
2063 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2064 flusing the whole TLB. */
2065 #if !defined(FLUSH_ALL_TLBS) && 0
2067 target_ulong page
, end
;
2068 /* Invalidate 256 MB of virtual memory */
2069 page
= (16 << 20) * srnum
;
2070 end
= page
+ (16 << 20);
2071 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
2072 tlb_flush_page(CPU(cpu
), page
);
2076 tlb_flush(CPU(cpu
), 1);
2081 /* TLB management */
2082 void helper_tlbia(CPUPPCState
*env
)
2084 ppc_tlb_invalidate_all(env
);
2087 void helper_tlbie(CPUPPCState
*env
, target_ulong addr
)
2089 ppc_tlb_invalidate_one(env
, addr
);
2092 void helper_tlbiva(CPUPPCState
*env
, target_ulong addr
)
2094 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2096 /* tlbiva instruction only exists on BookE */
2097 assert(env
->mmu_model
== POWERPC_MMU_BOOKE
);
2099 cpu_abort(CPU(cpu
), "BookE MMU model is not implemented\n");
2102 /* Software driven TLBs management */
2103 /* PowerPC 602/603 software TLB load instructions helpers */
2104 static void do_6xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2106 target_ulong RPN
, CMP
, EPN
;
2109 RPN
= env
->spr
[SPR_RPA
];
2111 CMP
= env
->spr
[SPR_ICMP
];
2112 EPN
= env
->spr
[SPR_IMISS
];
2114 CMP
= env
->spr
[SPR_DCMP
];
2115 EPN
= env
->spr
[SPR_DMISS
];
2117 way
= (env
->spr
[SPR_SRR1
] >> 17) & 1;
2118 (void)EPN
; /* avoid a compiler warning */
2119 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2120 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2122 /* Store this TLB */
2123 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2124 way
, is_code
, CMP
, RPN
);
2127 void helper_6xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2129 do_6xx_tlb(env
, EPN
, 0);
2132 void helper_6xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2134 do_6xx_tlb(env
, EPN
, 1);
2137 /* PowerPC 74xx software TLB load instructions helpers */
2138 static void do_74xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2140 target_ulong RPN
, CMP
, EPN
;
2143 RPN
= env
->spr
[SPR_PTELO
];
2144 CMP
= env
->spr
[SPR_PTEHI
];
2145 EPN
= env
->spr
[SPR_TLBMISS
] & ~0x3;
2146 way
= env
->spr
[SPR_TLBMISS
] & 0x3;
2147 (void)EPN
; /* avoid a compiler warning */
2148 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2149 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2151 /* Store this TLB */
2152 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2153 way
, is_code
, CMP
, RPN
);
2156 void helper_74xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2158 do_74xx_tlb(env
, EPN
, 0);
2161 void helper_74xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2163 do_74xx_tlb(env
, EPN
, 1);
2166 /*****************************************************************************/
2167 /* PowerPC 601 specific instructions (POWER bridge) */
2169 target_ulong
helper_rac(CPUPPCState
*env
, target_ulong addr
)
2173 target_ulong ret
= 0;
2175 /* We don't have to generate many instances of this instruction,
2176 * as rac is supervisor only.
2178 /* XXX: FIX THIS: Pretend we have no BAT */
2179 nb_BATs
= env
->nb_BATs
;
2181 if (get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) == 0) {
2184 env
->nb_BATs
= nb_BATs
;
2188 static inline target_ulong
booke_tlb_to_page_size(int size
)
2190 return 1024 << (2 * size
);
2193 static inline int booke_page_size_to_tlb(target_ulong page_size
)
2197 switch (page_size
) {
2231 #if defined(TARGET_PPC64)
2232 case 0x000100000000ULL
:
2235 case 0x000400000000ULL
:
2238 case 0x001000000000ULL
:
2241 case 0x004000000000ULL
:
2244 case 0x010000000000ULL
:
2256 /* Helpers for 4xx TLB management */
2257 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2259 #define PPC4XX_TLBHI_V 0x00000040
2260 #define PPC4XX_TLBHI_E 0x00000020
2261 #define PPC4XX_TLBHI_SIZE_MIN 0
2262 #define PPC4XX_TLBHI_SIZE_MAX 7
2263 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2264 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2265 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2267 #define PPC4XX_TLBLO_EX 0x00000200
2268 #define PPC4XX_TLBLO_WR 0x00000100
2269 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2270 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2272 target_ulong
helper_4xx_tlbre_hi(CPUPPCState
*env
, target_ulong entry
)
2278 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2279 tlb
= &env
->tlb
.tlbe
[entry
];
2281 if (tlb
->prot
& PAGE_VALID
) {
2282 ret
|= PPC4XX_TLBHI_V
;
2284 size
= booke_page_size_to_tlb(tlb
->size
);
2285 if (size
< PPC4XX_TLBHI_SIZE_MIN
|| size
> PPC4XX_TLBHI_SIZE_MAX
) {
2286 size
= PPC4XX_TLBHI_SIZE_DEFAULT
;
2288 ret
|= size
<< PPC4XX_TLBHI_SIZE_SHIFT
;
2289 env
->spr
[SPR_40x_PID
] = tlb
->PID
;
2293 target_ulong
helper_4xx_tlbre_lo(CPUPPCState
*env
, target_ulong entry
)
2298 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2299 tlb
= &env
->tlb
.tlbe
[entry
];
2301 if (tlb
->prot
& PAGE_EXEC
) {
2302 ret
|= PPC4XX_TLBLO_EX
;
2304 if (tlb
->prot
& PAGE_WRITE
) {
2305 ret
|= PPC4XX_TLBLO_WR
;
2310 void helper_4xx_tlbwe_hi(CPUPPCState
*env
, target_ulong entry
,
2313 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2314 CPUState
*cs
= CPU(cpu
);
2316 target_ulong page
, end
;
2318 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2320 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2321 tlb
= &env
->tlb
.tlbe
[entry
];
2322 /* Invalidate previous TLB (if it's valid) */
2323 if (tlb
->prot
& PAGE_VALID
) {
2324 end
= tlb
->EPN
+ tlb
->size
;
2325 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx
" end "
2326 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2327 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2328 tlb_flush_page(cs
, page
);
2331 tlb
->size
= booke_tlb_to_page_size((val
>> PPC4XX_TLBHI_SIZE_SHIFT
)
2332 & PPC4XX_TLBHI_SIZE_MASK
);
2333 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2334 * If this ever occurs, one should use the ppcemb target instead
2335 * of the ppc or ppc64 one
2337 if ((val
& PPC4XX_TLBHI_V
) && tlb
->size
< TARGET_PAGE_SIZE
) {
2338 cpu_abort(cs
, "TLB size " TARGET_FMT_lu
" < %u "
2339 "are not supported (%d)\n",
2340 tlb
->size
, TARGET_PAGE_SIZE
, (int)((val
>> 7) & 0x7));
2342 tlb
->EPN
= val
& ~(tlb
->size
- 1);
2343 if (val
& PPC4XX_TLBHI_V
) {
2344 tlb
->prot
|= PAGE_VALID
;
2345 if (val
& PPC4XX_TLBHI_E
) {
2346 /* XXX: TO BE FIXED */
2348 "Little-endian TLB entries are not supported by now\n");
2351 tlb
->prot
&= ~PAGE_VALID
;
2353 tlb
->PID
= env
->spr
[SPR_40x_PID
]; /* PID */
2354 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2355 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2356 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2357 tlb
->prot
& PAGE_READ
? 'r' : '-',
2358 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2359 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2360 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2361 /* Invalidate new TLB (if valid) */
2362 if (tlb
->prot
& PAGE_VALID
) {
2363 end
= tlb
->EPN
+ tlb
->size
;
2364 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx
" end "
2365 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2366 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2367 tlb_flush_page(cs
, page
);
2372 void helper_4xx_tlbwe_lo(CPUPPCState
*env
, target_ulong entry
,
2377 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2379 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2380 tlb
= &env
->tlb
.tlbe
[entry
];
2381 tlb
->attr
= val
& PPC4XX_TLBLO_ATTR_MASK
;
2382 tlb
->RPN
= val
& PPC4XX_TLBLO_RPN_MASK
;
2383 tlb
->prot
= PAGE_READ
;
2384 if (val
& PPC4XX_TLBLO_EX
) {
2385 tlb
->prot
|= PAGE_EXEC
;
2387 if (val
& PPC4XX_TLBLO_WR
) {
2388 tlb
->prot
|= PAGE_WRITE
;
2390 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2391 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2392 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2393 tlb
->prot
& PAGE_READ
? 'r' : '-',
2394 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2395 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2396 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2399 target_ulong
helper_4xx_tlbsx(CPUPPCState
*env
, target_ulong address
)
2401 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_40x_PID
]);
2404 /* PowerPC 440 TLB management */
2405 void helper_440_tlbwe(CPUPPCState
*env
, uint32_t word
, target_ulong entry
,
2408 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2410 target_ulong EPN
, RPN
, size
;
2413 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx
"\n",
2414 __func__
, word
, (int)entry
, value
);
2417 tlb
= &env
->tlb
.tlbe
[entry
];
2420 /* Just here to please gcc */
2422 EPN
= value
& 0xFFFFFC00;
2423 if ((tlb
->prot
& PAGE_VALID
) && EPN
!= tlb
->EPN
) {
2427 size
= booke_tlb_to_page_size((value
>> 4) & 0xF);
2428 if ((tlb
->prot
& PAGE_VALID
) && tlb
->size
< size
) {
2433 tlb
->attr
|= (value
>> 8) & 1;
2434 if (value
& 0x200) {
2435 tlb
->prot
|= PAGE_VALID
;
2437 if (tlb
->prot
& PAGE_VALID
) {
2438 tlb
->prot
&= ~PAGE_VALID
;
2442 tlb
->PID
= env
->spr
[SPR_440_MMUCR
] & 0x000000FF;
2443 if (do_flush_tlbs
) {
2444 tlb_flush(CPU(cpu
), 1);
2448 RPN
= value
& 0xFFFFFC0F;
2449 if ((tlb
->prot
& PAGE_VALID
) && tlb
->RPN
!= RPN
) {
2450 tlb_flush(CPU(cpu
), 1);
2455 tlb
->attr
= (tlb
->attr
& 0x1) | (value
& 0x0000FF00);
2456 tlb
->prot
= tlb
->prot
& PAGE_VALID
;
2458 tlb
->prot
|= PAGE_READ
<< 4;
2461 tlb
->prot
|= PAGE_WRITE
<< 4;
2464 tlb
->prot
|= PAGE_EXEC
<< 4;
2467 tlb
->prot
|= PAGE_READ
;
2470 tlb
->prot
|= PAGE_WRITE
;
2473 tlb
->prot
|= PAGE_EXEC
;
2479 target_ulong
helper_440_tlbre(CPUPPCState
*env
, uint32_t word
,
2487 tlb
= &env
->tlb
.tlbe
[entry
];
2490 /* Just here to please gcc */
2493 size
= booke_page_size_to_tlb(tlb
->size
);
2494 if (size
< 0 || size
> 0xF) {
2498 if (tlb
->attr
& 0x1) {
2501 if (tlb
->prot
& PAGE_VALID
) {
2504 env
->spr
[SPR_440_MMUCR
] &= ~0x000000FF;
2505 env
->spr
[SPR_440_MMUCR
] |= tlb
->PID
;
2511 ret
= tlb
->attr
& ~0x1;
2512 if (tlb
->prot
& (PAGE_READ
<< 4)) {
2515 if (tlb
->prot
& (PAGE_WRITE
<< 4)) {
2518 if (tlb
->prot
& (PAGE_EXEC
<< 4)) {
2521 if (tlb
->prot
& PAGE_READ
) {
2524 if (tlb
->prot
& PAGE_WRITE
) {
2527 if (tlb
->prot
& PAGE_EXEC
) {
2535 target_ulong
helper_440_tlbsx(CPUPPCState
*env
, target_ulong address
)
2537 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_440_MMUCR
] & 0xFF);
2540 /* PowerPC BookE 2.06 TLB management */
2542 static ppcmas_tlb_t
*booke206_cur_tlb(CPUPPCState
*env
)
2544 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2545 uint32_t tlbncfg
= 0;
2546 int esel
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ESEL_MASK
) >> MAS0_ESEL_SHIFT
;
2547 int ea
= (env
->spr
[SPR_BOOKE_MAS2
] & MAS2_EPN_MASK
);
2550 tlb
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2551 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlb
];
2553 if ((tlbncfg
& TLBnCFG_HES
) && (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_HES
)) {
2554 cpu_abort(CPU(cpu
), "we don't support HES yet\n");
2557 return booke206_get_tlbm(env
, tlb
, ea
, esel
);
2560 void helper_booke_setpid(CPUPPCState
*env
, uint32_t pidn
, target_ulong pid
)
2562 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2564 env
->spr
[pidn
] = pid
;
2565 /* changing PIDs mean we're in a different address space now */
2566 tlb_flush(CPU(cpu
), 1);
2569 void helper_booke206_tlbwe(CPUPPCState
*env
)
2571 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2572 uint32_t tlbncfg
, tlbn
;
2574 uint32_t size_tlb
, size_ps
;
2578 switch (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_WQ_MASK
) {
2579 case MAS0_WQ_ALWAYS
:
2580 /* good to go, write that entry */
2583 /* XXX check if reserved */
2588 case MAS0_WQ_CLR_RSRV
:
2589 /* XXX clear entry */
2592 /* no idea what to do */
2596 if (((env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ATSEL
) == MAS0_ATSEL_LRAT
) &&
2598 /* XXX we don't support direct LRAT setting yet */
2599 fprintf(stderr
, "cpu: don't support LRAT setting yet\n");
2603 tlbn
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2604 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlbn
];
2606 tlb
= booke206_cur_tlb(env
);
2609 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2610 POWERPC_EXCP_INVAL
|
2611 POWERPC_EXCP_INVAL_INVAL
);
2614 /* check that we support the targeted size */
2615 size_tlb
= (env
->spr
[SPR_BOOKE_MAS1
] & MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
2616 size_ps
= booke206_tlbnps(env
, tlbn
);
2617 if ((env
->spr
[SPR_BOOKE_MAS1
] & MAS1_VALID
) && (tlbncfg
& TLBnCFG_AVAIL
) &&
2618 !(size_ps
& (1 << size_tlb
))) {
2619 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2620 POWERPC_EXCP_INVAL
|
2621 POWERPC_EXCP_INVAL_INVAL
);
2625 cpu_abort(CPU(cpu
), "missing HV implementation\n");
2627 tlb
->mas7_3
= ((uint64_t)env
->spr
[SPR_BOOKE_MAS7
] << 32) |
2628 env
->spr
[SPR_BOOKE_MAS3
];
2629 tlb
->mas1
= env
->spr
[SPR_BOOKE_MAS1
];
2632 if (!(tlbncfg
& TLBnCFG_AVAIL
)) {
2633 /* force !AVAIL TLB entries to correct page size */
2634 tlb
->mas1
&= ~MAS1_TSIZE_MASK
;
2635 /* XXX can be configured in MMUCSR0 */
2636 tlb
->mas1
|= (tlbncfg
& TLBnCFG_MINSIZE
) >> 12;
2639 /* Make a mask from TLB size to discard invalid bits in EPN field */
2640 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2641 /* Add a mask for page attributes */
2642 mask
|= MAS2_ACM
| MAS2_VLE
| MAS2_W
| MAS2_I
| MAS2_M
| MAS2_G
| MAS2_E
;
2645 /* Executing a tlbwe instruction in 32-bit mode will set
2646 * bits 0:31 of the TLB EPN field to zero.
2651 tlb
->mas2
= env
->spr
[SPR_BOOKE_MAS2
] & mask
;
2653 if (!(tlbncfg
& TLBnCFG_IPROT
)) {
2654 /* no IPROT supported by TLB */
2655 tlb
->mas1
&= ~MAS1_IPROT
;
2658 if (booke206_tlb_to_page_size(env
, tlb
) == TARGET_PAGE_SIZE
) {
2659 tlb_flush_page(CPU(cpu
), tlb
->mas2
& MAS2_EPN_MASK
);
2661 tlb_flush(CPU(cpu
), 1);
2665 static inline void booke206_tlb_to_mas(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2667 int tlbn
= booke206_tlbm_to_tlbn(env
, tlb
);
2668 int way
= booke206_tlbm_to_way(env
, tlb
);
2670 env
->spr
[SPR_BOOKE_MAS0
] = tlbn
<< MAS0_TLBSEL_SHIFT
;
2671 env
->spr
[SPR_BOOKE_MAS0
] |= way
<< MAS0_ESEL_SHIFT
;
2672 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2674 env
->spr
[SPR_BOOKE_MAS1
] = tlb
->mas1
;
2675 env
->spr
[SPR_BOOKE_MAS2
] = tlb
->mas2
;
2676 env
->spr
[SPR_BOOKE_MAS3
] = tlb
->mas7_3
;
2677 env
->spr
[SPR_BOOKE_MAS7
] = tlb
->mas7_3
>> 32;
2680 void helper_booke206_tlbre(CPUPPCState
*env
)
2682 ppcmas_tlb_t
*tlb
= NULL
;
2684 tlb
= booke206_cur_tlb(env
);
2686 env
->spr
[SPR_BOOKE_MAS1
] = 0;
2688 booke206_tlb_to_mas(env
, tlb
);
2692 void helper_booke206_tlbsx(CPUPPCState
*env
, target_ulong address
)
2694 ppcmas_tlb_t
*tlb
= NULL
;
2699 spid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID_MASK
) >> MAS6_SPID_SHIFT
;
2700 sas
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
;
2702 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2703 int ways
= booke206_tlb_ways(env
, i
);
2705 for (j
= 0; j
< ways
; j
++) {
2706 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2712 if (ppcmas_tlb_check(env
, tlb
, &raddr
, address
, spid
)) {
2716 if (sas
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
2720 booke206_tlb_to_mas(env
, tlb
);
2725 /* no entry found, fill with defaults */
2726 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
2727 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
2728 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
2729 env
->spr
[SPR_BOOKE_MAS3
] = 0;
2730 env
->spr
[SPR_BOOKE_MAS7
] = 0;
2732 if (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
) {
2733 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
2736 env
->spr
[SPR_BOOKE_MAS1
] |= (env
->spr
[SPR_BOOKE_MAS6
] >> 16)
2739 /* next victim logic */
2740 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
2742 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
2743 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2746 static inline void booke206_invalidate_ea_tlb(CPUPPCState
*env
, int tlbn
,
2750 int ways
= booke206_tlb_ways(env
, tlbn
);
2753 for (i
= 0; i
< ways
; i
++) {
2754 ppcmas_tlb_t
*tlb
= booke206_get_tlbm(env
, tlbn
, ea
, i
);
2758 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2759 if (((tlb
->mas2
& MAS2_EPN_MASK
) == (ea
& mask
)) &&
2760 !(tlb
->mas1
& MAS1_IPROT
)) {
2761 tlb
->mas1
&= ~MAS1_VALID
;
2766 void helper_booke206_tlbivax(CPUPPCState
*env
, target_ulong address
)
2768 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2770 if (address
& 0x4) {
2771 /* flush all entries */
2772 if (address
& 0x8) {
2773 /* flush all of TLB1 */
2774 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB1
, 1);
2776 /* flush all of TLB0 */
2777 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB0
, 0);
2782 if (address
& 0x8) {
2783 /* flush TLB1 entries */
2784 booke206_invalidate_ea_tlb(env
, 1, address
);
2785 tlb_flush(CPU(cpu
), 1);
2787 /* flush TLB0 entries */
2788 booke206_invalidate_ea_tlb(env
, 0, address
);
2789 tlb_flush_page(CPU(cpu
), address
& MAS2_EPN_MASK
);
2793 void helper_booke206_tlbilx0(CPUPPCState
*env
, target_ulong address
)
2795 /* XXX missing LPID handling */
2796 booke206_flush_tlb(env
, -1, 1);
2799 void helper_booke206_tlbilx1(CPUPPCState
*env
, target_ulong address
)
2801 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2803 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2804 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
2807 /* XXX missing LPID handling */
2808 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2809 tlb_size
= booke206_tlb_size(env
, i
);
2810 for (j
= 0; j
< tlb_size
; j
++) {
2811 if (!(tlb
[j
].mas1
& MAS1_IPROT
) &&
2812 ((tlb
[j
].mas1
& MAS1_TID_MASK
) == tid
)) {
2813 tlb
[j
].mas1
&= ~MAS1_VALID
;
2816 tlb
+= booke206_tlb_size(env
, i
);
2818 tlb_flush(CPU(cpu
), 1);
2821 void helper_booke206_tlbilx3(CPUPPCState
*env
, target_ulong address
)
2823 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2826 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2827 int pid
= tid
>> MAS6_SPID_SHIFT
;
2828 int sgs
= env
->spr
[SPR_BOOKE_MAS5
] & MAS5_SGS
;
2829 int ind
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SIND
) ? MAS1_IND
: 0;
2830 /* XXX check for unsupported isize and raise an invalid opcode then */
2831 int size
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_ISIZE_MASK
;
2832 /* XXX implement MAV2 handling */
2835 /* XXX missing LPID handling */
2836 /* flush by pid and ea */
2837 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2838 int ways
= booke206_tlb_ways(env
, i
);
2840 for (j
= 0; j
< ways
; j
++) {
2841 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2845 if ((ppcmas_tlb_check(env
, tlb
, NULL
, address
, pid
) != 0) ||
2846 (tlb
->mas1
& MAS1_IPROT
) ||
2847 ((tlb
->mas1
& MAS1_IND
) != ind
) ||
2848 ((tlb
->mas8
& MAS8_TGS
) != sgs
)) {
2851 if (mav2
&& ((tlb
->mas1
& MAS1_TSIZE_MASK
) != size
)) {
2852 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2855 /* XXX e500mc doesn't match SAS, but other cores might */
2856 tlb
->mas1
&= ~MAS1_VALID
;
2859 tlb_flush(CPU(cpu
), 1);
2862 void helper_booke206_tlbflush(CPUPPCState
*env
, target_ulong type
)
2867 flags
|= BOOKE206_FLUSH_TLB1
;
2871 flags
|= BOOKE206_FLUSH_TLB0
;
2874 booke206_flush_tlb(env
, flags
, 1);
2878 /*****************************************************************************/
2880 /* try to fill the TLB and return an exception if error. If retaddr is
2881 NULL, it means that the function was called in C code (i.e. not
2882 from generated code or from helper.c) */
2883 /* XXX: fix it to restore all registers */
2884 void tlb_fill(CPUState
*cs
, target_ulong addr
, int is_write
, int mmu_idx
,
2887 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
2888 PowerPCCPUClass
*pcc
= POWERPC_CPU_GET_CLASS(cs
);
2889 CPUPPCState
*env
= &cpu
->env
;
2892 if (pcc
->handle_mmu_fault
) {
2893 ret
= pcc
->handle_mmu_fault(cpu
, addr
, is_write
, mmu_idx
);
2895 ret
= cpu_ppc_handle_mmu_fault(env
, addr
, is_write
, mmu_idx
);
2897 if (unlikely(ret
!= 0)) {
2898 if (likely(retaddr
)) {
2899 /* now we have a real cpu fault */
2900 cpu_restore_state(cs
, retaddr
);
2902 helper_raise_exception_err(env
, cs
->exception_index
, env
->error_code
);