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/>.
20 #include "exec/helper-proto.h"
21 #include "sysemu/kvm.h"
23 #include "mmu-hash64.h"
24 #include "mmu-hash32.h"
25 #include "exec/cpu_ldst.h"
29 //#define DEBUG_SOFTWARE_TLB
30 //#define DUMP_PAGE_TABLES
31 //#define DEBUG_SOFTWARE_TLB
32 //#define FLUSH_ALL_TLBS
35 # define LOG_MMU_STATE(cpu) log_cpu_state((cpu), 0)
37 # define LOG_MMU_STATE(cpu) do { } while (0)
40 #ifdef DEBUG_SOFTWARE_TLB
41 # define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
43 # define LOG_SWTLB(...) do { } while (0)
47 # define LOG_BATS(...) qemu_log(__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("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_enabled()) {
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("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 inline void ppc4xx_tlb_invalidate_virt(CPUPPCState
*env
,
662 target_ulong eaddr
, uint32_t pid
)
664 #if !defined(FLUSH_ALL_TLBS)
665 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
668 target_ulong page
, end
;
671 for (i
= 0; i
< env
->nb_tlb
; i
++) {
672 tlb
= &env
->tlb
.tlbe
[i
];
673 if (ppcemb_tlb_check(env
, tlb
, &raddr
, eaddr
, pid
, 0, i
) == 0) {
674 end
= tlb
->EPN
+ tlb
->size
;
675 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
676 tlb_flush_page(cs
, page
);
678 tlb
->prot
&= ~PAGE_VALID
;
683 ppc4xx_tlb_invalidate_all(env
);
687 static int mmu40x_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
688 target_ulong address
, int rw
,
693 int i
, ret
, zsel
, zpr
, pr
;
696 raddr
= (hwaddr
)-1ULL;
698 for (i
= 0; i
< env
->nb_tlb
; i
++) {
699 tlb
= &env
->tlb
.tlbe
[i
];
700 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
701 env
->spr
[SPR_40x_PID
], 0, i
) < 0) {
704 zsel
= (tlb
->attr
>> 4) & 0xF;
705 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (30 - (2 * zsel
))) & 0x3;
706 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
707 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
708 /* Check execute enable bit */
716 /* All accesses granted */
717 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
722 /* Raise Zone protection fault. */
723 env
->spr
[SPR_40x_ESR
] = 1 << 22;
731 /* Check from TLB entry */
732 ctx
->prot
= tlb
->prot
;
733 ret
= check_prot(ctx
->prot
, rw
, access_type
);
735 env
->spr
[SPR_40x_ESR
] = 0;
741 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
742 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
747 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
748 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
753 void store_40x_sler(CPUPPCState
*env
, uint32_t val
)
755 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
757 /* XXX: TO BE FIXED */
758 if (val
!= 0x00000000) {
759 cpu_abort(CPU(cpu
), "Little-endian regions are not supported by now\n");
761 env
->spr
[SPR_405_SLER
] = val
;
764 static inline int mmubooke_check_tlb(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
765 hwaddr
*raddr
, int *prot
,
766 target_ulong address
, int rw
,
767 int access_type
, int i
)
771 if (ppcemb_tlb_check(env
, tlb
, raddr
, address
,
772 env
->spr
[SPR_BOOKE_PID
],
773 !env
->nb_pids
, i
) >= 0) {
777 if (env
->spr
[SPR_BOOKE_PID1
] &&
778 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
779 env
->spr
[SPR_BOOKE_PID1
], 0, i
) >= 0) {
783 if (env
->spr
[SPR_BOOKE_PID2
] &&
784 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
785 env
->spr
[SPR_BOOKE_PID2
], 0, i
) >= 0) {
789 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
795 prot2
= tlb
->prot
& 0xF;
797 prot2
= (tlb
->prot
>> 4) & 0xF;
800 /* Check the address space */
801 if (access_type
== ACCESS_CODE
) {
802 if (msr_ir
!= (tlb
->attr
& 1)) {
803 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
808 if (prot2
& PAGE_EXEC
) {
809 LOG_SWTLB("%s: good TLB!\n", __func__
);
813 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
816 if (msr_dr
!= (tlb
->attr
& 1)) {
817 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
822 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
823 LOG_SWTLB("%s: found TLB!\n", __func__
);
827 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
834 static int mmubooke_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
835 target_ulong address
, int rw
,
843 raddr
= (hwaddr
)-1ULL;
844 for (i
= 0; i
< env
->nb_tlb
; i
++) {
845 tlb
= &env
->tlb
.tlbe
[i
];
846 ret
= mmubooke_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
, rw
,
855 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
856 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
859 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
860 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
866 static void booke206_flush_tlb(CPUPPCState
*env
, int flags
,
867 const int check_iprot
)
869 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
872 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
874 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
875 if (flags
& (1 << i
)) {
876 tlb_size
= booke206_tlb_size(env
, i
);
877 for (j
= 0; j
< tlb_size
; j
++) {
878 if (!check_iprot
|| !(tlb
[j
].mas1
& MAS1_IPROT
)) {
879 tlb
[j
].mas1
&= ~MAS1_VALID
;
883 tlb
+= booke206_tlb_size(env
, i
);
886 tlb_flush(CPU(cpu
), 1);
889 static hwaddr
booke206_tlb_to_page_size(CPUPPCState
*env
,
894 tlbm_size
= (tlb
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
896 return 1024ULL << tlbm_size
;
899 /* TLB check function for MAS based SoftTLBs */
900 static int ppcmas_tlb_check(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
901 hwaddr
*raddrp
, target_ulong address
,
908 /* In 32bit mode we can only address 32bit EAs */
909 address
= (uint32_t)address
;
912 /* Check valid flag */
913 if (!(tlb
->mas1
& MAS1_VALID
)) {
917 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
918 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx
" PID=0x%x MAS1=0x%x MAS2=0x%"
919 PRIx64
" mask=0x" TARGET_FMT_lx
" MAS7_3=0x%" PRIx64
" MAS8=%x\n",
920 __func__
, address
, pid
, tlb
->mas1
, tlb
->mas2
, mask
, tlb
->mas7_3
,
924 tlb_pid
= (tlb
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
;
925 if (tlb_pid
!= 0 && tlb_pid
!= pid
) {
929 /* Check effective address */
930 if ((address
& mask
) != (tlb
->mas2
& MAS2_EPN_MASK
)) {
935 *raddrp
= (tlb
->mas7_3
& mask
) | (address
& ~mask
);
941 static int mmubooke206_check_tlb(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
942 hwaddr
*raddr
, int *prot
,
943 target_ulong address
, int rw
,
949 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
,
950 env
->spr
[SPR_BOOKE_PID
]) >= 0) {
954 if (env
->spr
[SPR_BOOKE_PID1
] &&
955 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
956 env
->spr
[SPR_BOOKE_PID1
]) >= 0) {
960 if (env
->spr
[SPR_BOOKE_PID2
] &&
961 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
962 env
->spr
[SPR_BOOKE_PID2
]) >= 0) {
966 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
972 if (tlb
->mas7_3
& MAS3_UR
) {
975 if (tlb
->mas7_3
& MAS3_UW
) {
978 if (tlb
->mas7_3
& MAS3_UX
) {
982 if (tlb
->mas7_3
& MAS3_SR
) {
985 if (tlb
->mas7_3
& MAS3_SW
) {
988 if (tlb
->mas7_3
& MAS3_SX
) {
993 /* Check the address space and permissions */
994 if (access_type
== ACCESS_CODE
) {
995 if (msr_ir
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
996 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1001 if (prot2
& PAGE_EXEC
) {
1002 LOG_SWTLB("%s: good TLB!\n", __func__
);
1006 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
1009 if (msr_dr
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1010 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1015 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
1016 LOG_SWTLB("%s: found TLB!\n", __func__
);
1020 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
1027 static int mmubooke206_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1028 target_ulong address
, int rw
,
1036 raddr
= (hwaddr
)-1ULL;
1038 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1039 int ways
= booke206_tlb_ways(env
, i
);
1041 for (j
= 0; j
< ways
; j
++) {
1042 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
1046 ret
= mmubooke206_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
,
1058 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
1059 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1062 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
1063 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
1069 static const char *book3e_tsize_to_str
[32] = {
1070 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1071 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1072 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1076 static void mmubooke_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1079 ppcemb_tlb_t
*entry
;
1082 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1083 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1087 cpu_fprintf(f
, "\nTLB:\n");
1088 cpu_fprintf(f
, "Effective Physical Size PID Prot "
1091 entry
= &env
->tlb
.tlbe
[0];
1092 for (i
= 0; i
< env
->nb_tlb
; i
++, entry
++) {
1095 uint64_t size
= (uint64_t)entry
->size
;
1098 /* Check valid flag */
1099 if (!(entry
->prot
& PAGE_VALID
)) {
1103 mask
= ~(entry
->size
- 1);
1104 ea
= entry
->EPN
& mask
;
1105 pa
= entry
->RPN
& mask
;
1106 /* Extend the physical address to 36 bits */
1107 pa
|= (hwaddr
)(entry
->RPN
& 0xF) << 32;
1110 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"M", size
/ 1024);
1112 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"k", size
);
1114 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %s %-5u %08x %08x\n",
1115 (uint64_t)ea
, (uint64_t)pa
, size_buf
, (uint32_t)entry
->PID
,
1116 entry
->prot
, entry
->attr
);
1121 static void mmubooke206_dump_one_tlb(FILE *f
, fprintf_function cpu_fprintf
,
1122 CPUPPCState
*env
, int tlbn
, int offset
,
1125 ppcmas_tlb_t
*entry
;
1128 cpu_fprintf(f
, "\nTLB%d:\n", tlbn
);
1129 cpu_fprintf(f
, "Effective Physical Size TID TS SRWX"
1130 " URWX WIMGE U0123\n");
1132 entry
= &env
->tlb
.tlbm
[offset
];
1133 for (i
= 0; i
< tlbsize
; i
++, entry
++) {
1134 hwaddr ea
, pa
, size
;
1137 if (!(entry
->mas1
& MAS1_VALID
)) {
1141 tsize
= (entry
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1142 size
= 1024ULL << tsize
;
1143 ea
= entry
->mas2
& ~(size
- 1);
1144 pa
= entry
->mas7_3
& ~(size
- 1);
1146 cpu_fprintf(f
, "0x%016" PRIx64
" 0x%016" PRIx64
" %4s %-5u %1u S%c%c%c"
1147 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1148 (uint64_t)ea
, (uint64_t)pa
,
1149 book3e_tsize_to_str
[tsize
],
1150 (entry
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
,
1151 (entry
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
,
1152 entry
->mas7_3
& MAS3_SR
? 'R' : '-',
1153 entry
->mas7_3
& MAS3_SW
? 'W' : '-',
1154 entry
->mas7_3
& MAS3_SX
? 'X' : '-',
1155 entry
->mas7_3
& MAS3_UR
? 'R' : '-',
1156 entry
->mas7_3
& MAS3_UW
? 'W' : '-',
1157 entry
->mas7_3
& MAS3_UX
? 'X' : '-',
1158 entry
->mas2
& MAS2_W
? 'W' : '-',
1159 entry
->mas2
& MAS2_I
? 'I' : '-',
1160 entry
->mas2
& MAS2_M
? 'M' : '-',
1161 entry
->mas2
& MAS2_G
? 'G' : '-',
1162 entry
->mas2
& MAS2_E
? 'E' : '-',
1163 entry
->mas7_3
& MAS3_U0
? '0' : '-',
1164 entry
->mas7_3
& MAS3_U1
? '1' : '-',
1165 entry
->mas7_3
& MAS3_U2
? '2' : '-',
1166 entry
->mas7_3
& MAS3_U3
? '3' : '-');
1170 static void mmubooke206_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1176 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1177 cpu_fprintf(f
, "Cannot access KVM TLB\n");
1181 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1182 int size
= booke206_tlb_size(env
, i
);
1188 mmubooke206_dump_one_tlb(f
, cpu_fprintf
, env
, i
, offset
, size
);
1193 static void mmu6xx_dump_BATs(FILE *f
, fprintf_function cpu_fprintf
,
1194 CPUPPCState
*env
, int type
)
1196 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
1197 target_ulong BEPIl
, BEPIu
, bl
;
1202 BATlt
= env
->IBAT
[1];
1203 BATut
= env
->IBAT
[0];
1206 BATlt
= env
->DBAT
[1];
1207 BATut
= env
->DBAT
[0];
1211 for (i
= 0; i
< env
->nb_BATs
; i
++) {
1214 BEPIu
= *BATu
& 0xF0000000;
1215 BEPIl
= *BATu
& 0x0FFE0000;
1216 bl
= (*BATu
& 0x00001FFC) << 15;
1217 cpu_fprintf(f
, "%s BAT%d BATu " TARGET_FMT_lx
1218 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
1219 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
1220 type
== ACCESS_CODE
? "code" : "data", i
,
1221 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
1225 static void mmu6xx_dump_mmu(FILE *f
, fprintf_function cpu_fprintf
,
1230 int type
, way
, entry
, i
;
1232 cpu_fprintf(f
, "HTAB base = 0x%"HWADDR_PRIx
"\n", env
->htab_base
);
1233 cpu_fprintf(f
, "HTAB mask = 0x%"HWADDR_PRIx
"\n", env
->htab_mask
);
1235 cpu_fprintf(f
, "\nSegment registers:\n");
1236 for (i
= 0; i
< 32; i
++) {
1238 if (sr
& 0x80000000) {
1239 cpu_fprintf(f
, "%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1240 "CNTLR_SPEC=0x%05x\n", i
,
1241 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1242 sr
& 0x20000000 ? 1 : 0, (uint32_t)((sr
>> 20) & 0x1FF),
1243 (uint32_t)(sr
& 0xFFFFF));
1245 cpu_fprintf(f
, "%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i
,
1246 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1247 sr
& 0x20000000 ? 1 : 0, sr
& 0x10000000 ? 1 : 0,
1248 (uint32_t)(sr
& 0x00FFFFFF));
1252 cpu_fprintf(f
, "\nBATs:\n");
1253 mmu6xx_dump_BATs(f
, cpu_fprintf
, env
, ACCESS_INT
);
1254 mmu6xx_dump_BATs(f
, cpu_fprintf
, env
, ACCESS_CODE
);
1256 if (env
->id_tlbs
!= 1) {
1257 cpu_fprintf(f
, "ERROR: 6xx MMU should have separated TLB"
1258 " for code and data\n");
1261 cpu_fprintf(f
, "\nTLBs [EPN EPN + SIZE]\n");
1263 for (type
= 0; type
< 2; type
++) {
1264 for (way
= 0; way
< env
->nb_ways
; way
++) {
1265 for (entry
= env
->nb_tlb
* type
+ env
->tlb_per_way
* way
;
1266 entry
< (env
->nb_tlb
* type
+ env
->tlb_per_way
* (way
+ 1));
1269 tlb
= &env
->tlb
.tlb6
[entry
];
1270 cpu_fprintf(f
, "%s TLB %02d/%02d way:%d %s ["
1271 TARGET_FMT_lx
" " TARGET_FMT_lx
"]\n",
1272 type
? "code" : "data", entry
% env
->nb_tlb
,
1274 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
1275 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
);
1281 void dump_mmu(FILE *f
, fprintf_function cpu_fprintf
, CPUPPCState
*env
)
1283 switch (env
->mmu_model
) {
1284 case POWERPC_MMU_BOOKE
:
1285 mmubooke_dump_mmu(f
, cpu_fprintf
, env
);
1287 case POWERPC_MMU_BOOKE206
:
1288 mmubooke206_dump_mmu(f
, cpu_fprintf
, env
);
1290 case POWERPC_MMU_SOFT_6xx
:
1291 case POWERPC_MMU_SOFT_74xx
:
1292 mmu6xx_dump_mmu(f
, cpu_fprintf
, env
);
1294 #if defined(TARGET_PPC64)
1295 case POWERPC_MMU_64B
:
1296 case POWERPC_MMU_2_06
:
1297 case POWERPC_MMU_2_06a
:
1298 case POWERPC_MMU_2_06d
:
1299 dump_slb(f
, cpu_fprintf
, env
);
1303 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented\n", __func__
);
1307 static inline int check_physical(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1308 target_ulong eaddr
, int rw
)
1313 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1315 switch (env
->mmu_model
) {
1316 case POWERPC_MMU_SOFT_6xx
:
1317 case POWERPC_MMU_SOFT_74xx
:
1318 case POWERPC_MMU_SOFT_4xx
:
1319 case POWERPC_MMU_REAL
:
1320 case POWERPC_MMU_BOOKE
:
1321 ctx
->prot
|= PAGE_WRITE
;
1324 case POWERPC_MMU_SOFT_4xx_Z
:
1325 if (unlikely(msr_pe
!= 0)) {
1326 /* 403 family add some particular protections,
1327 * using PBL/PBU registers for accesses with no translation.
1330 /* Check PLB validity */
1331 (env
->pb
[0] < env
->pb
[1] &&
1332 /* and address in plb area */
1333 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1334 (env
->pb
[2] < env
->pb
[3] &&
1335 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1336 if (in_plb
^ msr_px
) {
1337 /* Access in protected area */
1339 /* Access is not allowed */
1343 /* Read-write access is allowed */
1344 ctx
->prot
|= PAGE_WRITE
;
1350 /* Caller's checks mean we should never get here for other models */
1358 static int get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1359 target_ulong eaddr
, int rw
, int access_type
)
1361 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1363 bool real_mode
= (access_type
== ACCESS_CODE
&& msr_ir
== 0)
1364 || (access_type
!= ACCESS_CODE
&& msr_dr
== 0);
1367 qemu_log("%s\n", __func__
);
1370 switch (env
->mmu_model
) {
1371 case POWERPC_MMU_SOFT_6xx
:
1372 case POWERPC_MMU_SOFT_74xx
:
1374 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1376 /* Try to find a BAT */
1377 if (env
->nb_BATs
!= 0) {
1378 ret
= get_bat_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1381 /* We didn't match any BAT entry or don't have BATs */
1382 ret
= get_segment_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1387 case POWERPC_MMU_SOFT_4xx
:
1388 case POWERPC_MMU_SOFT_4xx_Z
:
1390 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1392 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1396 case POWERPC_MMU_BOOKE
:
1397 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1400 case POWERPC_MMU_BOOKE206
:
1401 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1404 case POWERPC_MMU_MPC8xx
:
1406 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1408 case POWERPC_MMU_REAL
:
1410 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1412 cpu_abort(CPU(cpu
), "PowerPC in real mode do not do any translation\n");
1416 cpu_abort(CPU(cpu
), "Unknown or invalid MMU model\n");
1420 qemu_log("%s address " TARGET_FMT_lx
" => %d " TARGET_FMT_plx
"\n",
1421 __func__
, eaddr
, ret
, ctx
->raddr
);
1427 hwaddr
ppc_cpu_get_phys_page_debug(CPUState
*cs
, vaddr addr
)
1429 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
1430 CPUPPCState
*env
= &cpu
->env
;
1433 switch (env
->mmu_model
) {
1434 #if defined(TARGET_PPC64)
1435 case POWERPC_MMU_64B
:
1436 case POWERPC_MMU_2_06
:
1437 case POWERPC_MMU_2_06a
:
1438 case POWERPC_MMU_2_06d
:
1439 return ppc_hash64_get_phys_page_debug(env
, addr
);
1442 case POWERPC_MMU_32B
:
1443 case POWERPC_MMU_601
:
1444 return ppc_hash32_get_phys_page_debug(env
, addr
);
1450 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0)) {
1452 /* Some MMUs have separate TLBs for code and data. If we only try an
1453 * ACCESS_INT, we may not be able to read instructions mapped by code
1454 * TLBs, so we also try a ACCESS_CODE.
1456 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0,
1457 ACCESS_CODE
) != 0)) {
1462 return ctx
.raddr
& TARGET_PAGE_MASK
;
1465 static void booke206_update_mas_tlb_miss(CPUPPCState
*env
, target_ulong address
,
1468 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
1469 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
1470 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
1471 env
->spr
[SPR_BOOKE_MAS3
] = 0;
1472 env
->spr
[SPR_BOOKE_MAS6
] = 0;
1473 env
->spr
[SPR_BOOKE_MAS7
] = 0;
1476 if (((rw
== 2) && msr_ir
) || ((rw
!= 2) && msr_dr
)) {
1477 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
1478 env
->spr
[SPR_BOOKE_MAS6
] |= MAS6_SAS
;
1481 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_VALID
;
1482 env
->spr
[SPR_BOOKE_MAS2
] |= address
& MAS2_EPN_MASK
;
1484 switch (env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TIDSELD_PIDZ
) {
1485 case MAS4_TIDSELD_PID0
:
1486 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID
] << MAS1_TID_SHIFT
;
1488 case MAS4_TIDSELD_PID1
:
1489 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID1
] << MAS1_TID_SHIFT
;
1491 case MAS4_TIDSELD_PID2
:
1492 env
->spr
[SPR_BOOKE_MAS1
] |= env
->spr
[SPR_BOOKE_PID2
] << MAS1_TID_SHIFT
;
1496 env
->spr
[SPR_BOOKE_MAS6
] |= env
->spr
[SPR_BOOKE_PID
] << 16;
1498 /* next victim logic */
1499 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
1501 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
1502 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
1505 /* Perform address translation */
1506 static int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
,
1507 int rw
, int mmu_idx
)
1509 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1517 access_type
= ACCESS_CODE
;
1520 access_type
= env
->access_type
;
1522 ret
= get_physical_address(env
, &ctx
, address
, rw
, access_type
);
1524 tlb_set_page(cs
, address
& TARGET_PAGE_MASK
,
1525 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1526 mmu_idx
, TARGET_PAGE_SIZE
);
1528 } else if (ret
< 0) {
1530 if (access_type
== ACCESS_CODE
) {
1533 /* No matches in page tables or TLB */
1534 switch (env
->mmu_model
) {
1535 case POWERPC_MMU_SOFT_6xx
:
1536 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1537 env
->error_code
= 1 << 18;
1538 env
->spr
[SPR_IMISS
] = address
;
1539 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1541 case POWERPC_MMU_SOFT_74xx
:
1542 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1544 case POWERPC_MMU_SOFT_4xx
:
1545 case POWERPC_MMU_SOFT_4xx_Z
:
1546 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1547 env
->error_code
= 0;
1548 env
->spr
[SPR_40x_DEAR
] = address
;
1549 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1551 case POWERPC_MMU_BOOKE206
:
1552 booke206_update_mas_tlb_miss(env
, address
, rw
);
1554 case POWERPC_MMU_BOOKE
:
1555 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1556 env
->error_code
= 0;
1557 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1559 case POWERPC_MMU_MPC8xx
:
1561 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1563 case POWERPC_MMU_REAL
:
1564 cpu_abort(cs
, "PowerPC in real mode should never raise "
1565 "any MMU exceptions\n");
1568 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1573 /* Access rights violation */
1574 cs
->exception_index
= POWERPC_EXCP_ISI
;
1575 env
->error_code
= 0x08000000;
1578 /* No execute protection violation */
1579 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1580 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1581 env
->spr
[SPR_BOOKE_ESR
] = 0x00000000;
1583 cs
->exception_index
= POWERPC_EXCP_ISI
;
1584 env
->error_code
= 0x10000000;
1587 /* Direct store exception */
1588 /* No code fetch is allowed in direct-store areas */
1589 cs
->exception_index
= POWERPC_EXCP_ISI
;
1590 env
->error_code
= 0x10000000;
1596 /* No matches in page tables or TLB */
1597 switch (env
->mmu_model
) {
1598 case POWERPC_MMU_SOFT_6xx
:
1600 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1601 env
->error_code
= 1 << 16;
1603 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1604 env
->error_code
= 0;
1606 env
->spr
[SPR_DMISS
] = address
;
1607 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1609 env
->error_code
|= ctx
.key
<< 19;
1610 env
->spr
[SPR_HASH1
] = env
->htab_base
+
1611 get_pteg_offset32(env
, ctx
.hash
[0]);
1612 env
->spr
[SPR_HASH2
] = env
->htab_base
+
1613 get_pteg_offset32(env
, ctx
.hash
[1]);
1615 case POWERPC_MMU_SOFT_74xx
:
1617 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1619 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1622 /* Implement LRU algorithm */
1623 env
->error_code
= ctx
.key
<< 19;
1624 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1625 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1626 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1628 case POWERPC_MMU_SOFT_4xx
:
1629 case POWERPC_MMU_SOFT_4xx_Z
:
1630 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1631 env
->error_code
= 0;
1632 env
->spr
[SPR_40x_DEAR
] = address
;
1634 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1636 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1639 case POWERPC_MMU_MPC8xx
:
1641 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1643 case POWERPC_MMU_BOOKE206
:
1644 booke206_update_mas_tlb_miss(env
, address
, rw
);
1646 case POWERPC_MMU_BOOKE
:
1647 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1648 env
->error_code
= 0;
1649 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1650 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1652 case POWERPC_MMU_REAL
:
1653 cpu_abort(cs
, "PowerPC in real mode should never raise "
1654 "any MMU exceptions\n");
1657 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1662 /* Access rights violation */
1663 cs
->exception_index
= POWERPC_EXCP_DSI
;
1664 env
->error_code
= 0;
1665 if (env
->mmu_model
== POWERPC_MMU_SOFT_4xx
1666 || env
->mmu_model
== POWERPC_MMU_SOFT_4xx_Z
) {
1667 env
->spr
[SPR_40x_DEAR
] = address
;
1669 env
->spr
[SPR_40x_ESR
] |= 0x00800000;
1671 } else if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1672 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1673 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1674 env
->spr
[SPR_BOOKE_ESR
] = rw
? ESR_ST
: 0;
1676 env
->spr
[SPR_DAR
] = address
;
1678 env
->spr
[SPR_DSISR
] = 0x0A000000;
1680 env
->spr
[SPR_DSISR
] = 0x08000000;
1685 /* Direct store exception */
1686 switch (access_type
) {
1688 /* Floating point load/store */
1689 cs
->exception_index
= POWERPC_EXCP_ALIGN
;
1690 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1691 env
->spr
[SPR_DAR
] = address
;
1694 /* lwarx, ldarx or stwcx. */
1695 cs
->exception_index
= POWERPC_EXCP_DSI
;
1696 env
->error_code
= 0;
1697 env
->spr
[SPR_DAR
] = address
;
1699 env
->spr
[SPR_DSISR
] = 0x06000000;
1701 env
->spr
[SPR_DSISR
] = 0x04000000;
1705 /* eciwx or ecowx */
1706 cs
->exception_index
= POWERPC_EXCP_DSI
;
1707 env
->error_code
= 0;
1708 env
->spr
[SPR_DAR
] = address
;
1710 env
->spr
[SPR_DSISR
] = 0x06100000;
1712 env
->spr
[SPR_DSISR
] = 0x04100000;
1716 printf("DSI: invalid exception (%d)\n", ret
);
1717 cs
->exception_index
= POWERPC_EXCP_PROGRAM
;
1719 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1720 env
->spr
[SPR_DAR
] = address
;
1727 printf("%s: set exception to %d %02x\n", __func__
,
1728 cs
->exception
, env
->error_code
);
1736 /*****************************************************************************/
1737 /* BATs management */
1738 #if !defined(FLUSH_ALL_TLBS)
1739 static inline void do_invalidate_BAT(CPUPPCState
*env
, target_ulong BATu
,
1742 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1743 target_ulong base
, end
, page
;
1745 base
= BATu
& ~0x0001FFFF;
1746 end
= base
+ mask
+ 0x00020000;
1747 LOG_BATS("Flush BAT from " TARGET_FMT_lx
" to " TARGET_FMT_lx
" ("
1748 TARGET_FMT_lx
")\n", base
, end
, mask
);
1749 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
1750 tlb_flush_page(cs
, page
);
1752 LOG_BATS("Flush done\n");
1756 static inline void dump_store_bat(CPUPPCState
*env
, char ID
, int ul
, int nr
,
1759 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx
" (" TARGET_FMT_lx
")\n", ID
,
1760 nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1763 void helper_store_ibatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1767 dump_store_bat(env
, 'I', 0, nr
, value
);
1768 if (env
->IBAT
[0][nr
] != value
) {
1769 mask
= (value
<< 15) & 0x0FFE0000UL
;
1770 #if !defined(FLUSH_ALL_TLBS)
1771 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1773 /* When storing valid upper BAT, mask BEPI and BRPN
1774 * and invalidate all TLBs covered by this BAT
1776 mask
= (value
<< 15) & 0x0FFE0000UL
;
1777 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1778 (value
& ~0x0001FFFFUL
& ~mask
);
1779 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1780 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1781 #if !defined(FLUSH_ALL_TLBS)
1782 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1789 void helper_store_ibatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1791 dump_store_bat(env
, 'I', 1, nr
, value
);
1792 env
->IBAT
[1][nr
] = value
;
1795 void helper_store_dbatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1799 dump_store_bat(env
, 'D', 0, nr
, value
);
1800 if (env
->DBAT
[0][nr
] != value
) {
1801 /* When storing valid upper BAT, mask BEPI and BRPN
1802 * and invalidate all TLBs covered by this BAT
1804 mask
= (value
<< 15) & 0x0FFE0000UL
;
1805 #if !defined(FLUSH_ALL_TLBS)
1806 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1808 mask
= (value
<< 15) & 0x0FFE0000UL
;
1809 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1810 (value
& ~0x0001FFFFUL
& ~mask
);
1811 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1812 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1813 #if !defined(FLUSH_ALL_TLBS)
1814 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1821 void helper_store_dbatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1823 dump_store_bat(env
, 'D', 1, nr
, value
);
1824 env
->DBAT
[1][nr
] = value
;
1827 void helper_store_601_batu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1830 #if defined(FLUSH_ALL_TLBS)
1834 dump_store_bat(env
, 'I', 0, nr
, value
);
1835 if (env
->IBAT
[0][nr
] != value
) {
1836 #if defined(FLUSH_ALL_TLBS)
1839 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1840 if (env
->IBAT
[1][nr
] & 0x40) {
1841 /* Invalidate BAT only if it is valid */
1842 #if !defined(FLUSH_ALL_TLBS)
1843 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1848 /* When storing valid upper BAT, mask BEPI and BRPN
1849 * and invalidate all TLBs covered by this BAT
1851 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1852 (value
& ~0x0001FFFFUL
& ~mask
);
1853 env
->DBAT
[0][nr
] = env
->IBAT
[0][nr
];
1854 if (env
->IBAT
[1][nr
] & 0x40) {
1855 #if !defined(FLUSH_ALL_TLBS)
1856 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1861 #if defined(FLUSH_ALL_TLBS)
1869 void helper_store_601_batl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1871 #if !defined(FLUSH_ALL_TLBS)
1877 dump_store_bat(env
, 'I', 1, nr
, value
);
1878 if (env
->IBAT
[1][nr
] != value
) {
1879 #if defined(FLUSH_ALL_TLBS)
1882 if (env
->IBAT
[1][nr
] & 0x40) {
1883 #if !defined(FLUSH_ALL_TLBS)
1884 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1885 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1891 #if !defined(FLUSH_ALL_TLBS)
1892 mask
= (value
<< 17) & 0x0FFE0000UL
;
1893 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1898 env
->IBAT
[1][nr
] = value
;
1899 env
->DBAT
[1][nr
] = value
;
1900 #if defined(FLUSH_ALL_TLBS)
1908 /*****************************************************************************/
1909 /* TLB management */
1910 void ppc_tlb_invalidate_all(CPUPPCState
*env
)
1912 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1914 switch (env
->mmu_model
) {
1915 case POWERPC_MMU_SOFT_6xx
:
1916 case POWERPC_MMU_SOFT_74xx
:
1917 ppc6xx_tlb_invalidate_all(env
);
1919 case POWERPC_MMU_SOFT_4xx
:
1920 case POWERPC_MMU_SOFT_4xx_Z
:
1921 ppc4xx_tlb_invalidate_all(env
);
1923 case POWERPC_MMU_REAL
:
1924 cpu_abort(CPU(cpu
), "No TLB for PowerPC 4xx in real mode\n");
1926 case POWERPC_MMU_MPC8xx
:
1928 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1930 case POWERPC_MMU_BOOKE
:
1931 tlb_flush(CPU(cpu
), 1);
1933 case POWERPC_MMU_BOOKE206
:
1934 booke206_flush_tlb(env
, -1, 0);
1936 case POWERPC_MMU_32B
:
1937 case POWERPC_MMU_601
:
1938 #if defined(TARGET_PPC64)
1939 case POWERPC_MMU_64B
:
1940 case POWERPC_MMU_2_06
:
1941 case POWERPC_MMU_2_06a
:
1942 case POWERPC_MMU_2_06d
:
1943 #endif /* defined(TARGET_PPC64) */
1944 tlb_flush(CPU(cpu
), 1);
1948 cpu_abort(CPU(cpu
), "Unknown MMU model\n");
1953 void ppc_tlb_invalidate_one(CPUPPCState
*env
, target_ulong addr
)
1955 #if !defined(FLUSH_ALL_TLBS)
1956 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1959 addr
&= TARGET_PAGE_MASK
;
1960 switch (env
->mmu_model
) {
1961 case POWERPC_MMU_SOFT_6xx
:
1962 case POWERPC_MMU_SOFT_74xx
:
1963 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
1964 if (env
->id_tlbs
== 1) {
1965 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
1968 case POWERPC_MMU_SOFT_4xx
:
1969 case POWERPC_MMU_SOFT_4xx_Z
:
1970 ppc4xx_tlb_invalidate_virt(env
, addr
, env
->spr
[SPR_40x_PID
]);
1972 case POWERPC_MMU_REAL
:
1973 cpu_abort(CPU(cpu
), "No TLB for PowerPC 4xx in real mode\n");
1975 case POWERPC_MMU_MPC8xx
:
1977 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1979 case POWERPC_MMU_BOOKE
:
1981 cpu_abort(CPU(cpu
), "BookE MMU model is not implemented\n");
1983 case POWERPC_MMU_BOOKE206
:
1985 cpu_abort(CPU(cpu
), "BookE 2.06 MMU model is not implemented\n");
1987 case POWERPC_MMU_32B
:
1988 case POWERPC_MMU_601
:
1989 /* tlbie invalidate TLBs for all segments */
1990 addr
&= ~((target_ulong
)-1ULL << 28);
1992 /* XXX: this case should be optimized,
1993 * giving a mask to tlb_flush_page
1995 tlb_flush_page(cs
, addr
| (0x0 << 28));
1996 tlb_flush_page(cs
, addr
| (0x1 << 28));
1997 tlb_flush_page(cs
, addr
| (0x2 << 28));
1998 tlb_flush_page(cs
, addr
| (0x3 << 28));
1999 tlb_flush_page(cs
, addr
| (0x4 << 28));
2000 tlb_flush_page(cs
, addr
| (0x5 << 28));
2001 tlb_flush_page(cs
, addr
| (0x6 << 28));
2002 tlb_flush_page(cs
, addr
| (0x7 << 28));
2003 tlb_flush_page(cs
, addr
| (0x8 << 28));
2004 tlb_flush_page(cs
, addr
| (0x9 << 28));
2005 tlb_flush_page(cs
, addr
| (0xA << 28));
2006 tlb_flush_page(cs
, addr
| (0xB << 28));
2007 tlb_flush_page(cs
, addr
| (0xC << 28));
2008 tlb_flush_page(cs
, addr
| (0xD << 28));
2009 tlb_flush_page(cs
, addr
| (0xE << 28));
2010 tlb_flush_page(cs
, addr
| (0xF << 28));
2012 #if defined(TARGET_PPC64)
2013 case POWERPC_MMU_64B
:
2014 case POWERPC_MMU_2_06
:
2015 case POWERPC_MMU_2_06a
:
2016 case POWERPC_MMU_2_06d
:
2017 /* tlbie invalidate TLBs for all segments */
2018 /* XXX: given the fact that there are too many segments to invalidate,
2019 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
2020 * we just invalidate all TLBs
2022 tlb_flush(CPU(cpu
), 1);
2024 #endif /* defined(TARGET_PPC64) */
2027 cpu_abort(CPU(cpu
), "Unknown MMU model\n");
2031 ppc_tlb_invalidate_all(env
);
2035 /*****************************************************************************/
2036 /* Special registers manipulation */
2037 void ppc_store_sdr1(CPUPPCState
*env
, target_ulong value
)
2039 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2041 qemu_log_mask(CPU_LOG_MMU
, "%s: " TARGET_FMT_lx
"\n", __func__
, value
);
2042 assert(!env
->external_htab
);
2043 if (env
->spr
[SPR_SDR1
] != value
) {
2044 env
->spr
[SPR_SDR1
] = value
;
2045 #if defined(TARGET_PPC64)
2046 if (env
->mmu_model
& POWERPC_MMU_64
) {
2047 target_ulong htabsize
= value
& SDR_64_HTABSIZE
;
2049 if (htabsize
> 28) {
2050 fprintf(stderr
, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2051 " stored in SDR1\n", htabsize
);
2054 env
->htab_mask
= (1ULL << (htabsize
+ 18 - 7)) - 1;
2055 env
->htab_base
= value
& SDR_64_HTABORG
;
2057 #endif /* defined(TARGET_PPC64) */
2059 /* FIXME: Should check for valid HTABMASK values */
2060 env
->htab_mask
= ((value
& SDR_32_HTABMASK
) << 16) | 0xFFFF;
2061 env
->htab_base
= value
& SDR_32_HTABORG
;
2063 tlb_flush(CPU(cpu
), 1);
2067 /* Segment registers load and store */
2068 target_ulong
helper_load_sr(CPUPPCState
*env
, target_ulong sr_num
)
2070 #if defined(TARGET_PPC64)
2071 if (env
->mmu_model
& POWERPC_MMU_64
) {
2076 return env
->sr
[sr_num
];
2079 void helper_store_sr(CPUPPCState
*env
, target_ulong srnum
, target_ulong value
)
2081 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2083 qemu_log_mask(CPU_LOG_MMU
,
2084 "%s: reg=%d " TARGET_FMT_lx
" " TARGET_FMT_lx
"\n", __func__
,
2085 (int)srnum
, value
, env
->sr
[srnum
]);
2086 #if defined(TARGET_PPC64)
2087 if (env
->mmu_model
& POWERPC_MMU_64
) {
2088 uint64_t rb
= 0, rs
= 0;
2091 rb
|= ((uint32_t)srnum
& 0xf) << 28;
2092 /* Set the valid bit */
2095 rb
|= (uint32_t)srnum
;
2098 rs
|= (value
& 0xfffffff) << 12;
2100 rs
|= ((value
>> 27) & 0xf) << 8;
2102 ppc_store_slb(env
, rb
, rs
);
2105 if (env
->sr
[srnum
] != value
) {
2106 env
->sr
[srnum
] = value
;
2107 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2108 flusing the whole TLB. */
2109 #if !defined(FLUSH_ALL_TLBS) && 0
2111 target_ulong page
, end
;
2112 /* Invalidate 256 MB of virtual memory */
2113 page
= (16 << 20) * srnum
;
2114 end
= page
+ (16 << 20);
2115 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
2116 tlb_flush_page(CPU(cpu
), page
);
2120 tlb_flush(CPU(cpu
), 1);
2125 /* TLB management */
2126 void helper_tlbia(CPUPPCState
*env
)
2128 ppc_tlb_invalidate_all(env
);
2131 void helper_tlbie(CPUPPCState
*env
, target_ulong addr
)
2133 ppc_tlb_invalidate_one(env
, addr
);
2136 /* Software driven TLBs management */
2137 /* PowerPC 602/603 software TLB load instructions helpers */
2138 static void do_6xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2140 target_ulong RPN
, CMP
, EPN
;
2143 RPN
= env
->spr
[SPR_RPA
];
2145 CMP
= env
->spr
[SPR_ICMP
];
2146 EPN
= env
->spr
[SPR_IMISS
];
2148 CMP
= env
->spr
[SPR_DCMP
];
2149 EPN
= env
->spr
[SPR_DMISS
];
2151 way
= (env
->spr
[SPR_SRR1
] >> 17) & 1;
2152 (void)EPN
; /* avoid a compiler warning */
2153 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2154 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2156 /* Store this TLB */
2157 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2158 way
, is_code
, CMP
, RPN
);
2161 void helper_6xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2163 do_6xx_tlb(env
, EPN
, 0);
2166 void helper_6xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2168 do_6xx_tlb(env
, EPN
, 1);
2171 /* PowerPC 74xx software TLB load instructions helpers */
2172 static void do_74xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2174 target_ulong RPN
, CMP
, EPN
;
2177 RPN
= env
->spr
[SPR_PTELO
];
2178 CMP
= env
->spr
[SPR_PTEHI
];
2179 EPN
= env
->spr
[SPR_TLBMISS
] & ~0x3;
2180 way
= env
->spr
[SPR_TLBMISS
] & 0x3;
2181 (void)EPN
; /* avoid a compiler warning */
2182 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2183 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2185 /* Store this TLB */
2186 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2187 way
, is_code
, CMP
, RPN
);
2190 void helper_74xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2192 do_74xx_tlb(env
, EPN
, 0);
2195 void helper_74xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2197 do_74xx_tlb(env
, EPN
, 1);
2200 /*****************************************************************************/
2201 /* PowerPC 601 specific instructions (POWER bridge) */
2203 target_ulong
helper_rac(CPUPPCState
*env
, target_ulong addr
)
2207 target_ulong ret
= 0;
2209 /* We don't have to generate many instances of this instruction,
2210 * as rac is supervisor only.
2212 /* XXX: FIX THIS: Pretend we have no BAT */
2213 nb_BATs
= env
->nb_BATs
;
2215 if (get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) == 0) {
2218 env
->nb_BATs
= nb_BATs
;
2222 static inline target_ulong
booke_tlb_to_page_size(int size
)
2224 return 1024 << (2 * size
);
2227 static inline int booke_page_size_to_tlb(target_ulong page_size
)
2231 switch (page_size
) {
2265 #if defined(TARGET_PPC64)
2266 case 0x000100000000ULL
:
2269 case 0x000400000000ULL
:
2272 case 0x001000000000ULL
:
2275 case 0x004000000000ULL
:
2278 case 0x010000000000ULL
:
2290 /* Helpers for 4xx TLB management */
2291 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2293 #define PPC4XX_TLBHI_V 0x00000040
2294 #define PPC4XX_TLBHI_E 0x00000020
2295 #define PPC4XX_TLBHI_SIZE_MIN 0
2296 #define PPC4XX_TLBHI_SIZE_MAX 7
2297 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2298 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2299 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2301 #define PPC4XX_TLBLO_EX 0x00000200
2302 #define PPC4XX_TLBLO_WR 0x00000100
2303 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2304 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2306 target_ulong
helper_4xx_tlbre_hi(CPUPPCState
*env
, target_ulong entry
)
2312 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2313 tlb
= &env
->tlb
.tlbe
[entry
];
2315 if (tlb
->prot
& PAGE_VALID
) {
2316 ret
|= PPC4XX_TLBHI_V
;
2318 size
= booke_page_size_to_tlb(tlb
->size
);
2319 if (size
< PPC4XX_TLBHI_SIZE_MIN
|| size
> PPC4XX_TLBHI_SIZE_MAX
) {
2320 size
= PPC4XX_TLBHI_SIZE_DEFAULT
;
2322 ret
|= size
<< PPC4XX_TLBHI_SIZE_SHIFT
;
2323 env
->spr
[SPR_40x_PID
] = tlb
->PID
;
2327 target_ulong
helper_4xx_tlbre_lo(CPUPPCState
*env
, target_ulong entry
)
2332 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2333 tlb
= &env
->tlb
.tlbe
[entry
];
2335 if (tlb
->prot
& PAGE_EXEC
) {
2336 ret
|= PPC4XX_TLBLO_EX
;
2338 if (tlb
->prot
& PAGE_WRITE
) {
2339 ret
|= PPC4XX_TLBLO_WR
;
2344 void helper_4xx_tlbwe_hi(CPUPPCState
*env
, target_ulong entry
,
2347 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2348 CPUState
*cs
= CPU(cpu
);
2350 target_ulong page
, end
;
2352 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2354 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2355 tlb
= &env
->tlb
.tlbe
[entry
];
2356 /* Invalidate previous TLB (if it's valid) */
2357 if (tlb
->prot
& PAGE_VALID
) {
2358 end
= tlb
->EPN
+ tlb
->size
;
2359 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx
" end "
2360 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2361 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2362 tlb_flush_page(cs
, page
);
2365 tlb
->size
= booke_tlb_to_page_size((val
>> PPC4XX_TLBHI_SIZE_SHIFT
)
2366 & PPC4XX_TLBHI_SIZE_MASK
);
2367 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2368 * If this ever occurs, one should use the ppcemb target instead
2369 * of the ppc or ppc64 one
2371 if ((val
& PPC4XX_TLBHI_V
) && tlb
->size
< TARGET_PAGE_SIZE
) {
2372 cpu_abort(cs
, "TLB size " TARGET_FMT_lu
" < %u "
2373 "are not supported (%d)\n",
2374 tlb
->size
, TARGET_PAGE_SIZE
, (int)((val
>> 7) & 0x7));
2376 tlb
->EPN
= val
& ~(tlb
->size
- 1);
2377 if (val
& PPC4XX_TLBHI_V
) {
2378 tlb
->prot
|= PAGE_VALID
;
2379 if (val
& PPC4XX_TLBHI_E
) {
2380 /* XXX: TO BE FIXED */
2382 "Little-endian TLB entries are not supported by now\n");
2385 tlb
->prot
&= ~PAGE_VALID
;
2387 tlb
->PID
= env
->spr
[SPR_40x_PID
]; /* PID */
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
);
2395 /* Invalidate new TLB (if valid) */
2396 if (tlb
->prot
& PAGE_VALID
) {
2397 end
= tlb
->EPN
+ tlb
->size
;
2398 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx
" end "
2399 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2400 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2401 tlb_flush_page(cs
, page
);
2406 void helper_4xx_tlbwe_lo(CPUPPCState
*env
, target_ulong entry
,
2411 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2413 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2414 tlb
= &env
->tlb
.tlbe
[entry
];
2415 tlb
->attr
= val
& PPC4XX_TLBLO_ATTR_MASK
;
2416 tlb
->RPN
= val
& PPC4XX_TLBLO_RPN_MASK
;
2417 tlb
->prot
= PAGE_READ
;
2418 if (val
& PPC4XX_TLBLO_EX
) {
2419 tlb
->prot
|= PAGE_EXEC
;
2421 if (val
& PPC4XX_TLBLO_WR
) {
2422 tlb
->prot
|= PAGE_WRITE
;
2424 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2425 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2426 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2427 tlb
->prot
& PAGE_READ
? 'r' : '-',
2428 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2429 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2430 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2433 target_ulong
helper_4xx_tlbsx(CPUPPCState
*env
, target_ulong address
)
2435 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_40x_PID
]);
2438 /* PowerPC 440 TLB management */
2439 void helper_440_tlbwe(CPUPPCState
*env
, uint32_t word
, target_ulong entry
,
2442 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2444 target_ulong EPN
, RPN
, size
;
2447 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx
"\n",
2448 __func__
, word
, (int)entry
, value
);
2451 tlb
= &env
->tlb
.tlbe
[entry
];
2454 /* Just here to please gcc */
2456 EPN
= value
& 0xFFFFFC00;
2457 if ((tlb
->prot
& PAGE_VALID
) && EPN
!= tlb
->EPN
) {
2461 size
= booke_tlb_to_page_size((value
>> 4) & 0xF);
2462 if ((tlb
->prot
& PAGE_VALID
) && tlb
->size
< size
) {
2467 tlb
->attr
|= (value
>> 8) & 1;
2468 if (value
& 0x200) {
2469 tlb
->prot
|= PAGE_VALID
;
2471 if (tlb
->prot
& PAGE_VALID
) {
2472 tlb
->prot
&= ~PAGE_VALID
;
2476 tlb
->PID
= env
->spr
[SPR_440_MMUCR
] & 0x000000FF;
2477 if (do_flush_tlbs
) {
2478 tlb_flush(CPU(cpu
), 1);
2482 RPN
= value
& 0xFFFFFC0F;
2483 if ((tlb
->prot
& PAGE_VALID
) && tlb
->RPN
!= RPN
) {
2484 tlb_flush(CPU(cpu
), 1);
2489 tlb
->attr
= (tlb
->attr
& 0x1) | (value
& 0x0000FF00);
2490 tlb
->prot
= tlb
->prot
& PAGE_VALID
;
2492 tlb
->prot
|= PAGE_READ
<< 4;
2495 tlb
->prot
|= PAGE_WRITE
<< 4;
2498 tlb
->prot
|= PAGE_EXEC
<< 4;
2501 tlb
->prot
|= PAGE_READ
;
2504 tlb
->prot
|= PAGE_WRITE
;
2507 tlb
->prot
|= PAGE_EXEC
;
2513 target_ulong
helper_440_tlbre(CPUPPCState
*env
, uint32_t word
,
2521 tlb
= &env
->tlb
.tlbe
[entry
];
2524 /* Just here to please gcc */
2527 size
= booke_page_size_to_tlb(tlb
->size
);
2528 if (size
< 0 || size
> 0xF) {
2532 if (tlb
->attr
& 0x1) {
2535 if (tlb
->prot
& PAGE_VALID
) {
2538 env
->spr
[SPR_440_MMUCR
] &= ~0x000000FF;
2539 env
->spr
[SPR_440_MMUCR
] |= tlb
->PID
;
2545 ret
= tlb
->attr
& ~0x1;
2546 if (tlb
->prot
& (PAGE_READ
<< 4)) {
2549 if (tlb
->prot
& (PAGE_WRITE
<< 4)) {
2552 if (tlb
->prot
& (PAGE_EXEC
<< 4)) {
2555 if (tlb
->prot
& PAGE_READ
) {
2558 if (tlb
->prot
& PAGE_WRITE
) {
2561 if (tlb
->prot
& PAGE_EXEC
) {
2569 target_ulong
helper_440_tlbsx(CPUPPCState
*env
, target_ulong address
)
2571 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_440_MMUCR
] & 0xFF);
2574 /* PowerPC BookE 2.06 TLB management */
2576 static ppcmas_tlb_t
*booke206_cur_tlb(CPUPPCState
*env
)
2578 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2579 uint32_t tlbncfg
= 0;
2580 int esel
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ESEL_MASK
) >> MAS0_ESEL_SHIFT
;
2581 int ea
= (env
->spr
[SPR_BOOKE_MAS2
] & MAS2_EPN_MASK
);
2584 tlb
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2585 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlb
];
2587 if ((tlbncfg
& TLBnCFG_HES
) && (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_HES
)) {
2588 cpu_abort(CPU(cpu
), "we don't support HES yet\n");
2591 return booke206_get_tlbm(env
, tlb
, ea
, esel
);
2594 void helper_booke_setpid(CPUPPCState
*env
, uint32_t pidn
, target_ulong pid
)
2596 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2598 env
->spr
[pidn
] = pid
;
2599 /* changing PIDs mean we're in a different address space now */
2600 tlb_flush(CPU(cpu
), 1);
2603 void helper_booke206_tlbwe(CPUPPCState
*env
)
2605 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2606 uint32_t tlbncfg
, tlbn
;
2608 uint32_t size_tlb
, size_ps
;
2612 switch (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_WQ_MASK
) {
2613 case MAS0_WQ_ALWAYS
:
2614 /* good to go, write that entry */
2617 /* XXX check if reserved */
2622 case MAS0_WQ_CLR_RSRV
:
2623 /* XXX clear entry */
2626 /* no idea what to do */
2630 if (((env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ATSEL
) == MAS0_ATSEL_LRAT
) &&
2632 /* XXX we don't support direct LRAT setting yet */
2633 fprintf(stderr
, "cpu: don't support LRAT setting yet\n");
2637 tlbn
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2638 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlbn
];
2640 tlb
= booke206_cur_tlb(env
);
2643 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2644 POWERPC_EXCP_INVAL
|
2645 POWERPC_EXCP_INVAL_INVAL
);
2648 /* check that we support the targeted size */
2649 size_tlb
= (env
->spr
[SPR_BOOKE_MAS1
] & MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
2650 size_ps
= booke206_tlbnps(env
, tlbn
);
2651 if ((env
->spr
[SPR_BOOKE_MAS1
] & MAS1_VALID
) && (tlbncfg
& TLBnCFG_AVAIL
) &&
2652 !(size_ps
& (1 << size_tlb
))) {
2653 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
2654 POWERPC_EXCP_INVAL
|
2655 POWERPC_EXCP_INVAL_INVAL
);
2659 cpu_abort(CPU(cpu
), "missing HV implementation\n");
2661 tlb
->mas7_3
= ((uint64_t)env
->spr
[SPR_BOOKE_MAS7
] << 32) |
2662 env
->spr
[SPR_BOOKE_MAS3
];
2663 tlb
->mas1
= env
->spr
[SPR_BOOKE_MAS1
];
2666 if (!(tlbncfg
& TLBnCFG_AVAIL
)) {
2667 /* force !AVAIL TLB entries to correct page size */
2668 tlb
->mas1
&= ~MAS1_TSIZE_MASK
;
2669 /* XXX can be configured in MMUCSR0 */
2670 tlb
->mas1
|= (tlbncfg
& TLBnCFG_MINSIZE
) >> 12;
2673 /* Make a mask from TLB size to discard invalid bits in EPN field */
2674 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2675 /* Add a mask for page attributes */
2676 mask
|= MAS2_ACM
| MAS2_VLE
| MAS2_W
| MAS2_I
| MAS2_M
| MAS2_G
| MAS2_E
;
2679 /* Executing a tlbwe instruction in 32-bit mode will set
2680 * bits 0:31 of the TLB EPN field to zero.
2685 tlb
->mas2
= env
->spr
[SPR_BOOKE_MAS2
] & mask
;
2687 if (!(tlbncfg
& TLBnCFG_IPROT
)) {
2688 /* no IPROT supported by TLB */
2689 tlb
->mas1
&= ~MAS1_IPROT
;
2692 if (booke206_tlb_to_page_size(env
, tlb
) == TARGET_PAGE_SIZE
) {
2693 tlb_flush_page(CPU(cpu
), tlb
->mas2
& MAS2_EPN_MASK
);
2695 tlb_flush(CPU(cpu
), 1);
2699 static inline void booke206_tlb_to_mas(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2701 int tlbn
= booke206_tlbm_to_tlbn(env
, tlb
);
2702 int way
= booke206_tlbm_to_way(env
, tlb
);
2704 env
->spr
[SPR_BOOKE_MAS0
] = tlbn
<< MAS0_TLBSEL_SHIFT
;
2705 env
->spr
[SPR_BOOKE_MAS0
] |= way
<< MAS0_ESEL_SHIFT
;
2706 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2708 env
->spr
[SPR_BOOKE_MAS1
] = tlb
->mas1
;
2709 env
->spr
[SPR_BOOKE_MAS2
] = tlb
->mas2
;
2710 env
->spr
[SPR_BOOKE_MAS3
] = tlb
->mas7_3
;
2711 env
->spr
[SPR_BOOKE_MAS7
] = tlb
->mas7_3
>> 32;
2714 void helper_booke206_tlbre(CPUPPCState
*env
)
2716 ppcmas_tlb_t
*tlb
= NULL
;
2718 tlb
= booke206_cur_tlb(env
);
2720 env
->spr
[SPR_BOOKE_MAS1
] = 0;
2722 booke206_tlb_to_mas(env
, tlb
);
2726 void helper_booke206_tlbsx(CPUPPCState
*env
, target_ulong address
)
2728 ppcmas_tlb_t
*tlb
= NULL
;
2733 spid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID_MASK
) >> MAS6_SPID_SHIFT
;
2734 sas
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
;
2736 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2737 int ways
= booke206_tlb_ways(env
, i
);
2739 for (j
= 0; j
< ways
; j
++) {
2740 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2746 if (ppcmas_tlb_check(env
, tlb
, &raddr
, address
, spid
)) {
2750 if (sas
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
2754 booke206_tlb_to_mas(env
, tlb
);
2759 /* no entry found, fill with defaults */
2760 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
2761 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
2762 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
2763 env
->spr
[SPR_BOOKE_MAS3
] = 0;
2764 env
->spr
[SPR_BOOKE_MAS7
] = 0;
2766 if (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
) {
2767 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
2770 env
->spr
[SPR_BOOKE_MAS1
] |= (env
->spr
[SPR_BOOKE_MAS6
] >> 16)
2773 /* next victim logic */
2774 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
2776 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
2777 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2780 static inline void booke206_invalidate_ea_tlb(CPUPPCState
*env
, int tlbn
,
2784 int ways
= booke206_tlb_ways(env
, tlbn
);
2787 for (i
= 0; i
< ways
; i
++) {
2788 ppcmas_tlb_t
*tlb
= booke206_get_tlbm(env
, tlbn
, ea
, i
);
2792 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2793 if (((tlb
->mas2
& MAS2_EPN_MASK
) == (ea
& mask
)) &&
2794 !(tlb
->mas1
& MAS1_IPROT
)) {
2795 tlb
->mas1
&= ~MAS1_VALID
;
2800 void helper_booke206_tlbivax(CPUPPCState
*env
, target_ulong address
)
2802 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2804 if (address
& 0x4) {
2805 /* flush all entries */
2806 if (address
& 0x8) {
2807 /* flush all of TLB1 */
2808 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB1
, 1);
2810 /* flush all of TLB0 */
2811 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB0
, 0);
2816 if (address
& 0x8) {
2817 /* flush TLB1 entries */
2818 booke206_invalidate_ea_tlb(env
, 1, address
);
2819 tlb_flush(CPU(cpu
), 1);
2821 /* flush TLB0 entries */
2822 booke206_invalidate_ea_tlb(env
, 0, address
);
2823 tlb_flush_page(CPU(cpu
), address
& MAS2_EPN_MASK
);
2827 void helper_booke206_tlbilx0(CPUPPCState
*env
, target_ulong address
)
2829 /* XXX missing LPID handling */
2830 booke206_flush_tlb(env
, -1, 1);
2833 void helper_booke206_tlbilx1(CPUPPCState
*env
, target_ulong address
)
2835 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2837 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2838 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
2841 /* XXX missing LPID handling */
2842 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2843 tlb_size
= booke206_tlb_size(env
, i
);
2844 for (j
= 0; j
< tlb_size
; j
++) {
2845 if (!(tlb
[j
].mas1
& MAS1_IPROT
) &&
2846 ((tlb
[j
].mas1
& MAS1_TID_MASK
) == tid
)) {
2847 tlb
[j
].mas1
&= ~MAS1_VALID
;
2850 tlb
+= booke206_tlb_size(env
, i
);
2852 tlb_flush(CPU(cpu
), 1);
2855 void helper_booke206_tlbilx3(CPUPPCState
*env
, target_ulong address
)
2857 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2860 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2861 int pid
= tid
>> MAS6_SPID_SHIFT
;
2862 int sgs
= env
->spr
[SPR_BOOKE_MAS5
] & MAS5_SGS
;
2863 int ind
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SIND
) ? MAS1_IND
: 0;
2864 /* XXX check for unsupported isize and raise an invalid opcode then */
2865 int size
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_ISIZE_MASK
;
2866 /* XXX implement MAV2 handling */
2869 /* XXX missing LPID handling */
2870 /* flush by pid and ea */
2871 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2872 int ways
= booke206_tlb_ways(env
, i
);
2874 for (j
= 0; j
< ways
; j
++) {
2875 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2879 if ((ppcmas_tlb_check(env
, tlb
, NULL
, address
, pid
) != 0) ||
2880 (tlb
->mas1
& MAS1_IPROT
) ||
2881 ((tlb
->mas1
& MAS1_IND
) != ind
) ||
2882 ((tlb
->mas8
& MAS8_TGS
) != sgs
)) {
2885 if (mav2
&& ((tlb
->mas1
& MAS1_TSIZE_MASK
) != size
)) {
2886 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2889 /* XXX e500mc doesn't match SAS, but other cores might */
2890 tlb
->mas1
&= ~MAS1_VALID
;
2893 tlb_flush(CPU(cpu
), 1);
2896 void helper_booke206_tlbflush(CPUPPCState
*env
, target_ulong type
)
2901 flags
|= BOOKE206_FLUSH_TLB1
;
2905 flags
|= BOOKE206_FLUSH_TLB0
;
2908 booke206_flush_tlb(env
, flags
, 1);
2912 /*****************************************************************************/
2914 /* try to fill the TLB and return an exception if error. If retaddr is
2915 NULL, it means that the function was called in C code (i.e. not
2916 from generated code or from helper.c) */
2917 /* XXX: fix it to restore all registers */
2918 void tlb_fill(CPUState
*cs
, target_ulong addr
, int is_write
, int mmu_idx
,
2921 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
2922 PowerPCCPUClass
*pcc
= POWERPC_CPU_GET_CLASS(cs
);
2923 CPUPPCState
*env
= &cpu
->env
;
2926 if (pcc
->handle_mmu_fault
) {
2927 ret
= pcc
->handle_mmu_fault(cpu
, addr
, is_write
, mmu_idx
);
2929 ret
= cpu_ppc_handle_mmu_fault(env
, addr
, is_write
, mmu_idx
);
2931 if (unlikely(ret
!= 0)) {
2932 if (likely(retaddr
)) {
2933 /* now we have a real cpu fault */
2934 cpu_restore_state(cs
, retaddr
);
2936 helper_raise_exception_err(env
, cs
->exception_index
, env
->error_code
);