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 "qemu/units.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"
30 #include "helper_regs.h"
31 #include "qemu/error-report.h"
32 #include "qemu/qemu-print.h"
33 #include "mmu-book3s-v3.h"
34 #include "mmu-radix64.h"
36 /* #define DEBUG_MMU */
37 /* #define DEBUG_BATS */
38 /* #define DEBUG_SOFTWARE_TLB */
39 /* #define DUMP_PAGE_TABLES */
40 /* #define FLUSH_ALL_TLBS */
43 # define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0)
45 # define LOG_MMU_STATE(cpu) do { } while (0)
48 #ifdef DEBUG_SOFTWARE_TLB
49 # define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
51 # define LOG_SWTLB(...) do { } while (0)
55 # define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
57 # define LOG_BATS(...) do { } while (0)
60 /*****************************************************************************/
61 /* PowerPC MMU emulation */
63 /* Context used internally during MMU translations */
64 typedef struct mmu_ctx_t mmu_ctx_t
;
66 hwaddr raddr
; /* Real address */
67 hwaddr eaddr
; /* Effective address */
68 int prot
; /* Protection bits */
69 hwaddr hash
[2]; /* Pagetable hash values */
70 target_ulong ptem
; /* Virtual segment ID | API */
71 int key
; /* Access key */
72 int nx
; /* Non-execute area */
75 /* Common routines used by software and hardware TLBs emulation */
76 static inline int pte_is_valid(target_ulong pte0
)
78 return pte0
& 0x80000000 ? 1 : 0;
81 static inline void pte_invalidate(target_ulong
*pte0
)
86 #define PTE_PTEM_MASK 0x7FFFFFBF
87 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
89 static int pp_check(int key
, int pp
, int nx
)
93 /* Compute access rights */
100 access
|= PAGE_WRITE
;
116 access
= PAGE_READ
| PAGE_WRITE
;
127 static int check_prot(int prot
, int rw
, int access_type
)
131 if (access_type
== ACCESS_CODE
) {
132 if (prot
& PAGE_EXEC
) {
138 if (prot
& PAGE_WRITE
) {
144 if (prot
& PAGE_READ
) {
154 static inline int ppc6xx_tlb_pte_check(mmu_ctx_t
*ctx
, target_ulong pte0
,
155 target_ulong pte1
, int h
,
158 target_ulong ptem
, mmask
;
159 int access
, ret
, pteh
, ptev
, pp
;
162 /* Check validity and table match */
163 ptev
= pte_is_valid(pte0
);
164 pteh
= (pte0
>> 6) & 1;
165 if (ptev
&& h
== pteh
) {
166 /* Check vsid & api */
167 ptem
= pte0
& PTE_PTEM_MASK
;
168 mmask
= PTE_CHECK_MASK
;
169 pp
= pte1
& 0x00000003;
170 if (ptem
== ctx
->ptem
) {
171 if (ctx
->raddr
!= (hwaddr
)-1ULL) {
172 /* all matches should have equal RPN, WIMG & PP */
173 if ((ctx
->raddr
& mmask
) != (pte1
& mmask
)) {
174 qemu_log_mask(CPU_LOG_MMU
, "Bad RPN/WIMG/PP\n");
178 /* Compute access rights */
179 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
180 /* Keep the matching PTE informations */
183 ret
= check_prot(ctx
->prot
, rw
, type
);
186 qemu_log_mask(CPU_LOG_MMU
, "PTE access granted !\n");
188 /* Access right violation */
189 qemu_log_mask(CPU_LOG_MMU
, "PTE access rejected\n");
197 static int pte_update_flags(mmu_ctx_t
*ctx
, target_ulong
*pte1p
,
202 /* Update page flags */
203 if (!(*pte1p
& 0x00000100)) {
204 /* Update accessed flag */
205 *pte1p
|= 0x00000100;
208 if (!(*pte1p
& 0x00000080)) {
209 if (rw
== 1 && ret
== 0) {
210 /* Update changed flag */
211 *pte1p
|= 0x00000080;
214 /* Force page fault for first write access */
215 ctx
->prot
&= ~PAGE_WRITE
;
222 /* Software driven TLB helpers */
223 static inline int ppc6xx_tlb_getnum(CPUPPCState
*env
, target_ulong eaddr
,
224 int way
, int is_code
)
228 /* Select TLB num in a way from address */
229 nr
= (eaddr
>> TARGET_PAGE_BITS
) & (env
->tlb_per_way
- 1);
231 nr
+= env
->tlb_per_way
* way
;
232 /* 6xx have separate TLBs for instructions and data */
233 if (is_code
&& env
->id_tlbs
== 1) {
240 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState
*env
)
242 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
246 /* LOG_SWTLB("Invalidate all TLBs\n"); */
247 /* Invalidate all defined software TLB */
249 if (env
->id_tlbs
== 1) {
252 for (nr
= 0; nr
< max
; nr
++) {
253 tlb
= &env
->tlb
.tlb6
[nr
];
254 pte_invalidate(&tlb
->pte0
);
259 static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState
*env
,
261 int is_code
, int match_epn
)
263 #if !defined(FLUSH_ALL_TLBS)
264 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
268 /* Invalidate ITLB + DTLB, all ways */
269 for (way
= 0; way
< env
->nb_ways
; way
++) {
270 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
, is_code
);
271 tlb
= &env
->tlb
.tlb6
[nr
];
272 if (pte_is_valid(tlb
->pte0
) && (match_epn
== 0 || eaddr
== tlb
->EPN
)) {
273 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx
"\n", nr
,
275 pte_invalidate(&tlb
->pte0
);
276 tlb_flush_page(cs
, tlb
->EPN
);
280 /* XXX: PowerPC specification say this is valid as well */
281 ppc6xx_tlb_invalidate_all(env
);
285 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState
*env
,
286 target_ulong eaddr
, int is_code
)
288 ppc6xx_tlb_invalidate_virt2(env
, eaddr
, is_code
, 0);
291 static void ppc6xx_tlb_store(CPUPPCState
*env
, target_ulong EPN
, int way
,
292 int is_code
, target_ulong pte0
, target_ulong pte1
)
297 nr
= ppc6xx_tlb_getnum(env
, EPN
, way
, is_code
);
298 tlb
= &env
->tlb
.tlb6
[nr
];
299 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
300 " PTE1 " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
, EPN
, pte0
, pte1
);
301 /* Invalidate any pending reference in QEMU for this virtual address */
302 ppc6xx_tlb_invalidate_virt2(env
, EPN
, is_code
, 1);
306 /* Store last way for LRU mechanism */
310 static inline int ppc6xx_tlb_check(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
311 target_ulong eaddr
, int rw
, int access_type
)
318 ret
= -1; /* No TLB found */
319 for (way
= 0; way
< env
->nb_ways
; way
++) {
320 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
,
321 access_type
== ACCESS_CODE
? 1 : 0);
322 tlb
= &env
->tlb
.tlb6
[nr
];
323 /* This test "emulates" the PTE index match for hardware TLBs */
324 if ((eaddr
& TARGET_PAGE_MASK
) != tlb
->EPN
) {
325 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx
" " TARGET_FMT_lx
326 "] <> " TARGET_FMT_lx
"\n", nr
, env
->nb_tlb
,
327 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
328 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
, eaddr
);
331 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx
" <> " TARGET_FMT_lx
" "
332 TARGET_FMT_lx
" %c %c\n", nr
, env
->nb_tlb
,
333 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
334 tlb
->EPN
, eaddr
, tlb
->pte1
,
335 rw
? 'S' : 'L', access_type
== ACCESS_CODE
? 'I' : 'D');
336 switch (ppc6xx_tlb_pte_check(ctx
, tlb
->pte0
, tlb
->pte1
,
337 0, rw
, access_type
)) {
339 /* TLB inconsistency */
342 /* Access violation */
353 * XXX: we should go on looping to check all TLBs
354 * consistency but we can speed-up the whole thing as
355 * the result would be undefined if TLBs are not
365 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx
" prot=%01x ret=%d\n",
366 ctx
->raddr
& TARGET_PAGE_MASK
, ctx
->prot
, ret
);
367 /* Update page flags */
368 pte_update_flags(ctx
, &env
->tlb
.tlb6
[best
].pte1
, ret
, rw
);
374 /* Perform BAT hit & translation */
375 static inline void bat_size_prot(CPUPPCState
*env
, target_ulong
*blp
,
376 int *validp
, int *protp
, target_ulong
*BATu
,
382 bl
= (*BATu
& 0x00001FFC) << 15;
385 if (((msr_pr
== 0) && (*BATu
& 0x00000002)) ||
386 ((msr_pr
!= 0) && (*BATu
& 0x00000001))) {
388 pp
= *BATl
& 0x00000003;
390 prot
= PAGE_READ
| PAGE_EXEC
;
401 static int get_bat_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
402 target_ulong
virtual, int rw
, int type
)
404 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
405 target_ulong BEPIl
, BEPIu
, bl
;
409 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx
"\n", __func__
,
410 type
== ACCESS_CODE
? 'I' : 'D', virtual);
413 BATlt
= env
->IBAT
[1];
414 BATut
= env
->IBAT
[0];
417 BATlt
= env
->DBAT
[1];
418 BATut
= env
->DBAT
[0];
421 for (i
= 0; i
< env
->nb_BATs
; i
++) {
424 BEPIu
= *BATu
& 0xF0000000;
425 BEPIl
= *BATu
& 0x0FFE0000;
426 bat_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
427 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
428 " BATl " TARGET_FMT_lx
"\n", __func__
,
429 type
== ACCESS_CODE
? 'I' : 'D', i
, virtual, *BATu
, *BATl
);
430 if ((virtual & 0xF0000000) == BEPIu
&&
431 ((virtual & 0x0FFE0000) & ~bl
) == BEPIl
) {
434 /* Get physical address */
435 ctx
->raddr
= (*BATl
& 0xF0000000) |
436 ((virtual & 0x0FFE0000 & bl
) | (*BATl
& 0x0FFE0000)) |
437 (virtual & 0x0001F000);
438 /* Compute access rights */
440 ret
= check_prot(ctx
->prot
, rw
, type
);
442 LOG_BATS("BAT %d match: r " TARGET_FMT_plx
" prot=%c%c\n",
443 i
, ctx
->raddr
, ctx
->prot
& PAGE_READ
? 'R' : '-',
444 ctx
->prot
& PAGE_WRITE
? 'W' : '-');
451 #if defined(DEBUG_BATS)
452 if (qemu_log_enabled()) {
453 LOG_BATS("no BAT match for " TARGET_FMT_lx
":\n", virtual);
454 for (i
= 0; i
< 4; i
++) {
457 BEPIu
= *BATu
& 0xF0000000;
458 BEPIl
= *BATu
& 0x0FFE0000;
459 bl
= (*BATu
& 0x00001FFC) << 15;
460 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx
" BATu " TARGET_FMT_lx
461 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
462 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
463 __func__
, type
== ACCESS_CODE
? 'I' : 'D', i
, virtual,
464 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
473 /* Perform segment based translation */
474 static inline int get_segment_6xx_tlb(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
475 target_ulong eaddr
, int rw
, int type
)
477 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
480 int ds
, pr
, target_page_bits
;
482 target_ulong sr
, pgidx
;
487 sr
= env
->sr
[eaddr
>> 28];
488 ctx
->key
= (((sr
& 0x20000000) && (pr
!= 0)) ||
489 ((sr
& 0x40000000) && (pr
== 0))) ? 1 : 0;
490 ds
= sr
& 0x80000000 ? 1 : 0;
491 ctx
->nx
= sr
& 0x10000000 ? 1 : 0;
492 vsid
= sr
& 0x00FFFFFF;
493 target_page_bits
= TARGET_PAGE_BITS
;
494 qemu_log_mask(CPU_LOG_MMU
,
495 "Check segment v=" TARGET_FMT_lx
" %d " TARGET_FMT_lx
496 " nip=" TARGET_FMT_lx
" lr=" TARGET_FMT_lx
497 " ir=%d dr=%d pr=%d %d t=%d\n",
498 eaddr
, (int)(eaddr
>> 28), sr
, env
->nip
, env
->lr
, (int)msr_ir
,
499 (int)msr_dr
, pr
!= 0 ? 1 : 0, rw
, type
);
500 pgidx
= (eaddr
& ~SEGMENT_MASK_256M
) >> target_page_bits
;
502 ctx
->ptem
= (vsid
<< 7) | (pgidx
>> 10);
504 qemu_log_mask(CPU_LOG_MMU
,
505 "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx
"\n",
506 ctx
->key
, ds
, ctx
->nx
, vsid
);
509 /* Check if instruction fetch is allowed, if needed */
510 if (type
!= ACCESS_CODE
|| ctx
->nx
== 0) {
511 /* Page address translation */
512 qemu_log_mask(CPU_LOG_MMU
, "htab_base " TARGET_FMT_plx
513 " htab_mask " TARGET_FMT_plx
514 " hash " TARGET_FMT_plx
"\n",
515 ppc_hash32_hpt_base(cpu
), ppc_hash32_hpt_mask(cpu
), hash
);
517 ctx
->hash
[1] = ~hash
;
519 /* Initialize real address with an invalid value */
520 ctx
->raddr
= (hwaddr
)-1ULL;
521 /* Software TLB search */
522 ret
= ppc6xx_tlb_check(env
, ctx
, eaddr
, rw
, type
);
523 #if defined(DUMP_PAGE_TABLES)
524 if (qemu_loglevel_mask(CPU_LOG_MMU
)) {
525 CPUState
*cs
= ENV_GET_CPU(env
);
527 uint32_t a0
, a1
, a2
, a3
;
529 qemu_log("Page table: " TARGET_FMT_plx
" len " TARGET_FMT_plx
530 "\n", ppc_hash32_hpt_base(cpu
),
531 ppc_hash32_hpt_mask(env
) + 0x80);
532 for (curaddr
= ppc_hash32_hpt_base(cpu
);
533 curaddr
< (ppc_hash32_hpt_base(cpu
)
534 + ppc_hash32_hpt_mask(cpu
) + 0x80);
536 a0
= ldl_phys(cs
->as
, curaddr
);
537 a1
= ldl_phys(cs
->as
, curaddr
+ 4);
538 a2
= ldl_phys(cs
->as
, curaddr
+ 8);
539 a3
= ldl_phys(cs
->as
, curaddr
+ 12);
540 if (a0
!= 0 || a1
!= 0 || a2
!= 0 || a3
!= 0) {
541 qemu_log(TARGET_FMT_plx
": %08x %08x %08x %08x\n",
542 curaddr
, a0
, a1
, a2
, a3
);
548 qemu_log_mask(CPU_LOG_MMU
, "No access allowed\n");
554 qemu_log_mask(CPU_LOG_MMU
, "direct store...\n");
555 /* Direct-store segment : absolutely *BUGGY* for now */
558 * Direct-store implies a 32-bit MMU.
559 * Check the Segment Register's bus unit ID (BUID).
561 sr
= env
->sr
[eaddr
>> 28];
562 if ((sr
& 0x1FF00000) >> 20 == 0x07f) {
564 * Memory-forced I/O controller interface access
566 * If T=1 and BUID=x'07F', the 601 performs a memory
567 * access to SR[28-31] LA[4-31], bypassing all protection
570 ctx
->raddr
= ((sr
& 0xF) << 28) | (eaddr
& 0x0FFFFFFF);
571 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
577 /* Integer load/store : only access allowed */
580 /* No code fetch is allowed in direct-store areas */
583 /* Floating point load/store */
586 /* lwarx, ldarx or srwcx. */
590 * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
592 * Should make the instruction do no-op. As it already do
593 * no-op, it's quite easy :-)
601 qemu_log_mask(CPU_LOG_MMU
, "ERROR: instruction should not need "
602 "address translation\n");
605 if ((rw
== 1 || ctx
->key
!= 1) && (rw
== 0 || ctx
->key
!= 0)) {
616 /* Generic TLB check function for embedded PowerPC implementations */
617 static int ppcemb_tlb_check(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
619 target_ulong address
, uint32_t pid
, int ext
,
624 /* Check valid flag */
625 if (!(tlb
->prot
& PAGE_VALID
)) {
628 mask
= ~(tlb
->size
- 1);
629 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx
" PID %u <=> " TARGET_FMT_lx
630 " " TARGET_FMT_lx
" %u %x\n", __func__
, i
, address
, pid
, tlb
->EPN
,
631 mask
, (uint32_t)tlb
->PID
, tlb
->prot
);
633 if (tlb
->PID
!= 0 && tlb
->PID
!= pid
) {
636 /* Check effective address */
637 if ((address
& mask
) != tlb
->EPN
) {
640 *raddrp
= (tlb
->RPN
& mask
) | (address
& ~mask
);
642 /* Extend the physical address to 36 bits */
643 *raddrp
|= (uint64_t)(tlb
->RPN
& 0xF) << 32;
649 /* Generic TLB search function for PowerPC embedded implementations */
650 static int ppcemb_tlb_search(CPUPPCState
*env
, target_ulong address
,
657 /* Default return value is no match */
659 for (i
= 0; i
< env
->nb_tlb
; i
++) {
660 tlb
= &env
->tlb
.tlbe
[i
];
661 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
, pid
, 0, i
) == 0) {
670 /* Helpers specific to PowerPC 40x implementations */
671 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState
*env
)
673 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
677 for (i
= 0; i
< env
->nb_tlb
; i
++) {
678 tlb
= &env
->tlb
.tlbe
[i
];
679 tlb
->prot
&= ~PAGE_VALID
;
684 static int mmu40x_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
685 target_ulong address
, int rw
,
690 int i
, ret
, zsel
, zpr
, pr
;
693 raddr
= (hwaddr
)-1ULL;
695 for (i
= 0; i
< env
->nb_tlb
; i
++) {
696 tlb
= &env
->tlb
.tlbe
[i
];
697 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
698 env
->spr
[SPR_40x_PID
], 0, i
) < 0) {
701 zsel
= (tlb
->attr
>> 4) & 0xF;
702 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (30 - (2 * zsel
))) & 0x3;
703 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
704 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
705 /* Check execute enable bit */
713 /* All accesses granted */
714 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
719 /* Raise Zone protection fault. */
720 env
->spr
[SPR_40x_ESR
] = 1 << 22;
728 /* Check from TLB entry */
729 ctx
->prot
= tlb
->prot
;
730 ret
= check_prot(ctx
->prot
, rw
, access_type
);
732 env
->spr
[SPR_40x_ESR
] = 0;
738 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
739 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
744 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
745 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
750 void store_40x_sler(CPUPPCState
*env
, uint32_t val
)
752 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
754 /* XXX: TO BE FIXED */
755 if (val
!= 0x00000000) {
756 cpu_abort(CPU(cpu
), "Little-endian regions are not supported by now\n");
758 env
->spr
[SPR_405_SLER
] = val
;
761 static inline int mmubooke_check_tlb(CPUPPCState
*env
, ppcemb_tlb_t
*tlb
,
762 hwaddr
*raddr
, int *prot
,
763 target_ulong address
, int rw
,
764 int access_type
, int i
)
768 if (ppcemb_tlb_check(env
, tlb
, raddr
, address
,
769 env
->spr
[SPR_BOOKE_PID
],
770 !env
->nb_pids
, i
) >= 0) {
774 if (env
->spr
[SPR_BOOKE_PID1
] &&
775 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
776 env
->spr
[SPR_BOOKE_PID1
], 0, i
) >= 0) {
780 if (env
->spr
[SPR_BOOKE_PID2
] &&
781 ppcemb_tlb_check(env
, tlb
, raddr
, address
,
782 env
->spr
[SPR_BOOKE_PID2
], 0, i
) >= 0) {
786 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
792 prot2
= tlb
->prot
& 0xF;
794 prot2
= (tlb
->prot
>> 4) & 0xF;
797 /* Check the address space */
798 if (access_type
== ACCESS_CODE
) {
799 if (msr_ir
!= (tlb
->attr
& 1)) {
800 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
805 if (prot2
& PAGE_EXEC
) {
806 LOG_SWTLB("%s: good TLB!\n", __func__
);
810 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
813 if (msr_dr
!= (tlb
->attr
& 1)) {
814 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
819 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
820 LOG_SWTLB("%s: found TLB!\n", __func__
);
824 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
831 static int mmubooke_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
832 target_ulong address
, int rw
,
840 raddr
= (hwaddr
)-1ULL;
841 for (i
= 0; i
< env
->nb_tlb
; i
++) {
842 tlb
= &env
->tlb
.tlbe
[i
];
843 ret
= mmubooke_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
, rw
,
852 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
853 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
856 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
857 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
863 static void booke206_flush_tlb(CPUPPCState
*env
, int flags
,
864 const int check_iprot
)
866 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
869 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
871 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
872 if (flags
& (1 << i
)) {
873 tlb_size
= booke206_tlb_size(env
, i
);
874 for (j
= 0; j
< tlb_size
; j
++) {
875 if (!check_iprot
|| !(tlb
[j
].mas1
& MAS1_IPROT
)) {
876 tlb
[j
].mas1
&= ~MAS1_VALID
;
880 tlb
+= booke206_tlb_size(env
, i
);
886 static hwaddr
booke206_tlb_to_page_size(CPUPPCState
*env
,
891 tlbm_size
= (tlb
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
893 return 1024ULL << tlbm_size
;
896 /* TLB check function for MAS based SoftTLBs */
897 static int ppcmas_tlb_check(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
898 hwaddr
*raddrp
, target_ulong address
,
905 /* In 32bit mode we can only address 32bit EAs */
906 address
= (uint32_t)address
;
909 /* Check valid flag */
910 if (!(tlb
->mas1
& MAS1_VALID
)) {
914 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
915 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx
" PID=0x%x MAS1=0x%x MAS2=0x%"
916 PRIx64
" mask=0x%" HWADDR_PRIx
" MAS7_3=0x%" PRIx64
" MAS8=0x%"
917 PRIx32
"\n", __func__
, address
, pid
, tlb
->mas1
, tlb
->mas2
, mask
,
918 tlb
->mas7_3
, tlb
->mas8
);
921 tlb_pid
= (tlb
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
;
922 if (tlb_pid
!= 0 && tlb_pid
!= pid
) {
926 /* Check effective address */
927 if ((address
& mask
) != (tlb
->mas2
& MAS2_EPN_MASK
)) {
932 *raddrp
= (tlb
->mas7_3
& mask
) | (address
& ~mask
);
938 static bool is_epid_mmu(int mmu_idx
)
940 return mmu_idx
== PPC_TLB_EPID_STORE
|| mmu_idx
== PPC_TLB_EPID_LOAD
;
943 static uint32_t mmubooke206_esr(int mmu_idx
, bool rw
)
949 if (is_epid_mmu(mmu_idx
)) {
956 * Get EPID register given the mmu_idx. If this is regular load,
957 * construct the EPID access bits from current processor state
959 * Get the effective AS and PR bits and the PID. The PID is returned
960 * only if EPID load is requested, otherwise the caller must detect
961 * the correct EPID. Return true if valid EPID is returned.
963 static bool mmubooke206_get_as(CPUPPCState
*env
,
964 int mmu_idx
, uint32_t *epid_out
,
965 bool *as_out
, bool *pr_out
)
967 if (is_epid_mmu(mmu_idx
)) {
969 if (mmu_idx
== PPC_TLB_EPID_STORE
) {
970 epidr
= env
->spr
[SPR_BOOKE_EPSC
];
972 epidr
= env
->spr
[SPR_BOOKE_EPLC
];
974 *epid_out
= (epidr
& EPID_EPID
) >> EPID_EPID_SHIFT
;
975 *as_out
= !!(epidr
& EPID_EAS
);
976 *pr_out
= !!(epidr
& EPID_EPR
);
985 /* Check if the tlb found by hashing really matches */
986 static int mmubooke206_check_tlb(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
,
987 hwaddr
*raddr
, int *prot
,
988 target_ulong address
, int rw
,
989 int access_type
, int mmu_idx
)
995 bool use_epid
= mmubooke206_get_as(env
, mmu_idx
, &epid
, &as
, &pr
);
998 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
,
999 env
->spr
[SPR_BOOKE_PID
]) >= 0) {
1003 if (env
->spr
[SPR_BOOKE_PID1
] &&
1004 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
1005 env
->spr
[SPR_BOOKE_PID1
]) >= 0) {
1009 if (env
->spr
[SPR_BOOKE_PID2
] &&
1010 ppcmas_tlb_check(env
, tlb
, raddr
, address
,
1011 env
->spr
[SPR_BOOKE_PID2
]) >= 0) {
1015 if (ppcmas_tlb_check(env
, tlb
, raddr
, address
, epid
) >= 0) {
1020 LOG_SWTLB("%s: TLB entry not found\n", __func__
);
1026 if (tlb
->mas7_3
& MAS3_UR
) {
1029 if (tlb
->mas7_3
& MAS3_UW
) {
1030 prot2
|= PAGE_WRITE
;
1032 if (tlb
->mas7_3
& MAS3_UX
) {
1036 if (tlb
->mas7_3
& MAS3_SR
) {
1039 if (tlb
->mas7_3
& MAS3_SW
) {
1040 prot2
|= PAGE_WRITE
;
1042 if (tlb
->mas7_3
& MAS3_SX
) {
1047 /* Check the address space and permissions */
1048 if (access_type
== ACCESS_CODE
) {
1049 /* There is no way to fetch code using epid load */
1051 if (msr_ir
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1052 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1057 if (prot2
& PAGE_EXEC
) {
1058 LOG_SWTLB("%s: good TLB!\n", __func__
);
1062 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__
, prot2
);
1065 if (as
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
1066 LOG_SWTLB("%s: AS doesn't match\n", __func__
);
1071 if ((!rw
&& prot2
& PAGE_READ
) || (rw
&& (prot2
& PAGE_WRITE
))) {
1072 LOG_SWTLB("%s: found TLB!\n", __func__
);
1076 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__
, prot2
);
1083 static int mmubooke206_get_physical_address(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1084 target_ulong address
, int rw
,
1085 int access_type
, int mmu_idx
)
1092 raddr
= (hwaddr
)-1ULL;
1094 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1095 int ways
= booke206_tlb_ways(env
, i
);
1097 for (j
= 0; j
< ways
; j
++) {
1098 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
1102 ret
= mmubooke206_check_tlb(env
, tlb
, &raddr
, &ctx
->prot
, address
,
1103 rw
, access_type
, mmu_idx
);
1114 LOG_SWTLB("%s: access granted " TARGET_FMT_lx
" => " TARGET_FMT_plx
1115 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1118 LOG_SWTLB("%s: access refused " TARGET_FMT_lx
" => " TARGET_FMT_plx
1119 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
, ret
);
1125 static const char *book3e_tsize_to_str
[32] = {
1126 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1127 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1128 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1132 static void mmubooke_dump_mmu(CPUPPCState
*env
)
1134 ppcemb_tlb_t
*entry
;
1137 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1138 qemu_printf("Cannot access KVM TLB\n");
1142 qemu_printf("\nTLB:\n");
1143 qemu_printf("Effective Physical Size PID Prot "
1146 entry
= &env
->tlb
.tlbe
[0];
1147 for (i
= 0; i
< env
->nb_tlb
; i
++, entry
++) {
1150 uint64_t size
= (uint64_t)entry
->size
;
1153 /* Check valid flag */
1154 if (!(entry
->prot
& PAGE_VALID
)) {
1158 mask
= ~(entry
->size
- 1);
1159 ea
= entry
->EPN
& mask
;
1160 pa
= entry
->RPN
& mask
;
1161 /* Extend the physical address to 36 bits */
1162 pa
|= (hwaddr
)(entry
->RPN
& 0xF) << 32;
1163 if (size
>= 1 * MiB
) {
1164 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"M", size
/ MiB
);
1166 snprintf(size_buf
, sizeof(size_buf
), "%3" PRId64
"k", size
/ KiB
);
1168 qemu_printf("0x%016" PRIx64
" 0x%016" PRIx64
" %s %-5u %08x %08x\n",
1169 (uint64_t)ea
, (uint64_t)pa
, size_buf
, (uint32_t)entry
->PID
,
1170 entry
->prot
, entry
->attr
);
1175 static void mmubooke206_dump_one_tlb(CPUPPCState
*env
, int tlbn
, int offset
,
1178 ppcmas_tlb_t
*entry
;
1181 qemu_printf("\nTLB%d:\n", tlbn
);
1182 qemu_printf("Effective Physical Size TID TS SRWX"
1183 " URWX WIMGE U0123\n");
1185 entry
= &env
->tlb
.tlbm
[offset
];
1186 for (i
= 0; i
< tlbsize
; i
++, entry
++) {
1187 hwaddr ea
, pa
, size
;
1190 if (!(entry
->mas1
& MAS1_VALID
)) {
1194 tsize
= (entry
->mas1
& MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
1195 size
= 1024ULL << tsize
;
1196 ea
= entry
->mas2
& ~(size
- 1);
1197 pa
= entry
->mas7_3
& ~(size
- 1);
1199 qemu_printf("0x%016" PRIx64
" 0x%016" PRIx64
" %4s %-5u %1u S%c%c%c"
1200 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1201 (uint64_t)ea
, (uint64_t)pa
,
1202 book3e_tsize_to_str
[tsize
],
1203 (entry
->mas1
& MAS1_TID_MASK
) >> MAS1_TID_SHIFT
,
1204 (entry
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
,
1205 entry
->mas7_3
& MAS3_SR
? 'R' : '-',
1206 entry
->mas7_3
& MAS3_SW
? 'W' : '-',
1207 entry
->mas7_3
& MAS3_SX
? 'X' : '-',
1208 entry
->mas7_3
& MAS3_UR
? 'R' : '-',
1209 entry
->mas7_3
& MAS3_UW
? 'W' : '-',
1210 entry
->mas7_3
& MAS3_UX
? 'X' : '-',
1211 entry
->mas2
& MAS2_W
? 'W' : '-',
1212 entry
->mas2
& MAS2_I
? 'I' : '-',
1213 entry
->mas2
& MAS2_M
? 'M' : '-',
1214 entry
->mas2
& MAS2_G
? 'G' : '-',
1215 entry
->mas2
& MAS2_E
? 'E' : '-',
1216 entry
->mas7_3
& MAS3_U0
? '0' : '-',
1217 entry
->mas7_3
& MAS3_U1
? '1' : '-',
1218 entry
->mas7_3
& MAS3_U2
? '2' : '-',
1219 entry
->mas7_3
& MAS3_U3
? '3' : '-');
1223 static void mmubooke206_dump_mmu(CPUPPCState
*env
)
1228 if (kvm_enabled() && !env
->kvm_sw_tlb
) {
1229 qemu_printf("Cannot access KVM TLB\n");
1233 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
1234 int size
= booke206_tlb_size(env
, i
);
1240 mmubooke206_dump_one_tlb(env
, i
, offset
, size
);
1245 static void mmu6xx_dump_BATs(CPUPPCState
*env
, int type
)
1247 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
1248 target_ulong BEPIl
, BEPIu
, bl
;
1253 BATlt
= env
->IBAT
[1];
1254 BATut
= env
->IBAT
[0];
1257 BATlt
= env
->DBAT
[1];
1258 BATut
= env
->DBAT
[0];
1262 for (i
= 0; i
< env
->nb_BATs
; i
++) {
1265 BEPIu
= *BATu
& 0xF0000000;
1266 BEPIl
= *BATu
& 0x0FFE0000;
1267 bl
= (*BATu
& 0x00001FFC) << 15;
1268 qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
1269 " BATl " TARGET_FMT_lx
"\n\t" TARGET_FMT_lx
" "
1270 TARGET_FMT_lx
" " TARGET_FMT_lx
"\n",
1271 type
== ACCESS_CODE
? "code" : "data", i
,
1272 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
1276 static void mmu6xx_dump_mmu(CPUPPCState
*env
)
1278 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1281 int type
, way
, entry
, i
;
1283 qemu_printf("HTAB base = 0x%"HWADDR_PRIx
"\n", ppc_hash32_hpt_base(cpu
));
1284 qemu_printf("HTAB mask = 0x%"HWADDR_PRIx
"\n", ppc_hash32_hpt_mask(cpu
));
1286 qemu_printf("\nSegment registers:\n");
1287 for (i
= 0; i
< 32; i
++) {
1289 if (sr
& 0x80000000) {
1290 qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1291 "CNTLR_SPEC=0x%05x\n", i
,
1292 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1293 sr
& 0x20000000 ? 1 : 0, (uint32_t)((sr
>> 20) & 0x1FF),
1294 (uint32_t)(sr
& 0xFFFFF));
1296 qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i
,
1297 sr
& 0x80000000 ? 1 : 0, sr
& 0x40000000 ? 1 : 0,
1298 sr
& 0x20000000 ? 1 : 0, sr
& 0x10000000 ? 1 : 0,
1299 (uint32_t)(sr
& 0x00FFFFFF));
1303 qemu_printf("\nBATs:\n");
1304 mmu6xx_dump_BATs(env
, ACCESS_INT
);
1305 mmu6xx_dump_BATs(env
, ACCESS_CODE
);
1307 if (env
->id_tlbs
!= 1) {
1308 qemu_printf("ERROR: 6xx MMU should have separated TLB"
1309 " for code and data\n");
1312 qemu_printf("\nTLBs [EPN EPN + SIZE]\n");
1314 for (type
= 0; type
< 2; type
++) {
1315 for (way
= 0; way
< env
->nb_ways
; way
++) {
1316 for (entry
= env
->nb_tlb
* type
+ env
->tlb_per_way
* way
;
1317 entry
< (env
->nb_tlb
* type
+ env
->tlb_per_way
* (way
+ 1));
1320 tlb
= &env
->tlb
.tlb6
[entry
];
1321 qemu_printf("%s TLB %02d/%02d way:%d %s ["
1322 TARGET_FMT_lx
" " TARGET_FMT_lx
"]\n",
1323 type
? "code" : "data", entry
% env
->nb_tlb
,
1325 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
1326 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
);
1332 void dump_mmu(CPUPPCState
*env
)
1334 switch (env
->mmu_model
) {
1335 case POWERPC_MMU_BOOKE
:
1336 mmubooke_dump_mmu(env
);
1338 case POWERPC_MMU_BOOKE206
:
1339 mmubooke206_dump_mmu(env
);
1341 case POWERPC_MMU_SOFT_6xx
:
1342 case POWERPC_MMU_SOFT_74xx
:
1343 mmu6xx_dump_mmu(env
);
1345 #if defined(TARGET_PPC64)
1346 case POWERPC_MMU_64B
:
1347 case POWERPC_MMU_2_03
:
1348 case POWERPC_MMU_2_06
:
1349 case POWERPC_MMU_2_07
:
1350 dump_slb(ppc_env_get_cpu(env
));
1352 case POWERPC_MMU_3_00
:
1353 if (ppc64_v3_radix(ppc_env_get_cpu(env
))) {
1354 /* TODO - Unsupported */
1356 dump_slb(ppc_env_get_cpu(env
));
1361 qemu_log_mask(LOG_UNIMP
, "%s: unimplemented\n", __func__
);
1365 static inline int check_physical(CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1366 target_ulong eaddr
, int rw
)
1371 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1373 switch (env
->mmu_model
) {
1374 case POWERPC_MMU_SOFT_6xx
:
1375 case POWERPC_MMU_SOFT_74xx
:
1376 case POWERPC_MMU_SOFT_4xx
:
1377 case POWERPC_MMU_REAL
:
1378 case POWERPC_MMU_BOOKE
:
1379 ctx
->prot
|= PAGE_WRITE
;
1382 case POWERPC_MMU_SOFT_4xx_Z
:
1383 if (unlikely(msr_pe
!= 0)) {
1385 * 403 family add some particular protections, using
1386 * PBL/PBU registers for accesses with no translation.
1389 /* Check PLB validity */
1390 (env
->pb
[0] < env
->pb
[1] &&
1391 /* and address in plb area */
1392 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1393 (env
->pb
[2] < env
->pb
[3] &&
1394 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1395 if (in_plb
^ msr_px
) {
1396 /* Access in protected area */
1398 /* Access is not allowed */
1402 /* Read-write access is allowed */
1403 ctx
->prot
|= PAGE_WRITE
;
1409 /* Caller's checks mean we should never get here for other models */
1417 static int get_physical_address_wtlb(
1418 CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1419 target_ulong eaddr
, int rw
, int access_type
,
1422 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1424 bool real_mode
= (access_type
== ACCESS_CODE
&& msr_ir
== 0)
1425 || (access_type
!= ACCESS_CODE
&& msr_dr
== 0);
1427 switch (env
->mmu_model
) {
1428 case POWERPC_MMU_SOFT_6xx
:
1429 case POWERPC_MMU_SOFT_74xx
:
1431 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1433 /* Try to find a BAT */
1434 if (env
->nb_BATs
!= 0) {
1435 ret
= get_bat_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1438 /* We didn't match any BAT entry or don't have BATs */
1439 ret
= get_segment_6xx_tlb(env
, ctx
, eaddr
, rw
, access_type
);
1444 case POWERPC_MMU_SOFT_4xx
:
1445 case POWERPC_MMU_SOFT_4xx_Z
:
1447 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1449 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1453 case POWERPC_MMU_BOOKE
:
1454 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1457 case POWERPC_MMU_BOOKE206
:
1458 ret
= mmubooke206_get_physical_address(env
, ctx
, eaddr
, rw
,
1459 access_type
, mmu_idx
);
1461 case POWERPC_MMU_MPC8xx
:
1463 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
1465 case POWERPC_MMU_REAL
:
1467 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1470 "PowerPC in real mode do not do any translation\n");
1474 cpu_abort(CPU(cpu
), "Unknown or invalid MMU model\n");
1481 static int get_physical_address(
1482 CPUPPCState
*env
, mmu_ctx_t
*ctx
,
1483 target_ulong eaddr
, int rw
, int access_type
)
1485 return get_physical_address_wtlb(env
, ctx
, eaddr
, rw
, access_type
, 0);
1488 hwaddr
ppc_cpu_get_phys_page_debug(CPUState
*cs
, vaddr addr
)
1490 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
1491 CPUPPCState
*env
= &cpu
->env
;
1494 switch (env
->mmu_model
) {
1495 #if defined(TARGET_PPC64)
1496 case POWERPC_MMU_64B
:
1497 case POWERPC_MMU_2_03
:
1498 case POWERPC_MMU_2_06
:
1499 case POWERPC_MMU_2_07
:
1500 return ppc_hash64_get_phys_page_debug(cpu
, addr
);
1501 case POWERPC_MMU_3_00
:
1502 return ppc64_v3_get_phys_page_debug(cpu
, addr
);
1505 case POWERPC_MMU_32B
:
1506 case POWERPC_MMU_601
:
1507 return ppc_hash32_get_phys_page_debug(cpu
, addr
);
1513 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0)) {
1516 * Some MMUs have separate TLBs for code and data. If we only
1517 * try an ACCESS_INT, we may not be able to read instructions
1518 * mapped by code TLBs, so we also try a ACCESS_CODE.
1520 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0,
1521 ACCESS_CODE
) != 0)) {
1526 return ctx
.raddr
& TARGET_PAGE_MASK
;
1529 static void booke206_update_mas_tlb_miss(CPUPPCState
*env
, target_ulong address
,
1530 int rw
, int mmu_idx
)
1534 uint32_t missed_tid
= 0;
1535 bool use_epid
= mmubooke206_get_as(env
, mmu_idx
, &epid
, &as
, &pr
);
1539 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
1540 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
1541 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
1542 env
->spr
[SPR_BOOKE_MAS3
] = 0;
1543 env
->spr
[SPR_BOOKE_MAS6
] = 0;
1544 env
->spr
[SPR_BOOKE_MAS7
] = 0;
1548 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
1549 env
->spr
[SPR_BOOKE_MAS6
] |= MAS6_SAS
;
1552 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_VALID
;
1553 env
->spr
[SPR_BOOKE_MAS2
] |= address
& MAS2_EPN_MASK
;
1556 switch (env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TIDSELD_PIDZ
) {
1557 case MAS4_TIDSELD_PID0
:
1558 missed_tid
= env
->spr
[SPR_BOOKE_PID
];
1560 case MAS4_TIDSELD_PID1
:
1561 missed_tid
= env
->spr
[SPR_BOOKE_PID1
];
1563 case MAS4_TIDSELD_PID2
:
1564 missed_tid
= env
->spr
[SPR_BOOKE_PID2
];
1567 env
->spr
[SPR_BOOKE_MAS6
] |= env
->spr
[SPR_BOOKE_PID
] << 16;
1570 env
->spr
[SPR_BOOKE_MAS6
] |= missed_tid
<< 16;
1572 env
->spr
[SPR_BOOKE_MAS1
] |= (missed_tid
<< MAS1_TID_SHIFT
);
1575 /* next victim logic */
1576 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
1578 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
1579 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
1582 /* Perform address translation */
1583 static int cpu_ppc_handle_mmu_fault(CPUPPCState
*env
, target_ulong address
,
1584 int rw
, int mmu_idx
)
1586 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1587 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
1595 access_type
= ACCESS_CODE
;
1598 access_type
= env
->access_type
;
1600 ret
= get_physical_address_wtlb(env
, &ctx
, address
, rw
,
1601 access_type
, mmu_idx
);
1603 tlb_set_page(cs
, address
& TARGET_PAGE_MASK
,
1604 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1605 mmu_idx
, TARGET_PAGE_SIZE
);
1607 } else if (ret
< 0) {
1609 if (access_type
== ACCESS_CODE
) {
1612 /* No matches in page tables or TLB */
1613 switch (env
->mmu_model
) {
1614 case POWERPC_MMU_SOFT_6xx
:
1615 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1616 env
->error_code
= 1 << 18;
1617 env
->spr
[SPR_IMISS
] = address
;
1618 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1620 case POWERPC_MMU_SOFT_74xx
:
1621 cs
->exception_index
= POWERPC_EXCP_IFTLB
;
1623 case POWERPC_MMU_SOFT_4xx
:
1624 case POWERPC_MMU_SOFT_4xx_Z
:
1625 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1626 env
->error_code
= 0;
1627 env
->spr
[SPR_40x_DEAR
] = address
;
1628 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1630 case POWERPC_MMU_BOOKE206
:
1631 booke206_update_mas_tlb_miss(env
, address
, 2, mmu_idx
);
1633 case POWERPC_MMU_BOOKE
:
1634 cs
->exception_index
= POWERPC_EXCP_ITLB
;
1635 env
->error_code
= 0;
1636 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1637 env
->spr
[SPR_BOOKE_ESR
] = mmubooke206_esr(mmu_idx
, 0);
1639 case POWERPC_MMU_MPC8xx
:
1641 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1643 case POWERPC_MMU_REAL
:
1644 cpu_abort(cs
, "PowerPC in real mode should never raise "
1645 "any MMU exceptions\n");
1648 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1653 /* Access rights violation */
1654 cs
->exception_index
= POWERPC_EXCP_ISI
;
1655 env
->error_code
= 0x08000000;
1658 /* No execute protection violation */
1659 if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1660 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1661 env
->spr
[SPR_BOOKE_ESR
] = 0x00000000;
1663 cs
->exception_index
= POWERPC_EXCP_ISI
;
1664 env
->error_code
= 0x10000000;
1667 /* Direct store exception */
1668 /* No code fetch is allowed in direct-store areas */
1669 cs
->exception_index
= POWERPC_EXCP_ISI
;
1670 env
->error_code
= 0x10000000;
1676 /* No matches in page tables or TLB */
1677 switch (env
->mmu_model
) {
1678 case POWERPC_MMU_SOFT_6xx
:
1680 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1681 env
->error_code
= 1 << 16;
1683 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1684 env
->error_code
= 0;
1686 env
->spr
[SPR_DMISS
] = address
;
1687 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1689 env
->error_code
|= ctx
.key
<< 19;
1690 env
->spr
[SPR_HASH1
] = ppc_hash32_hpt_base(cpu
) +
1691 get_pteg_offset32(cpu
, ctx
.hash
[0]);
1692 env
->spr
[SPR_HASH2
] = ppc_hash32_hpt_base(cpu
) +
1693 get_pteg_offset32(cpu
, ctx
.hash
[1]);
1695 case POWERPC_MMU_SOFT_74xx
:
1697 cs
->exception_index
= POWERPC_EXCP_DSTLB
;
1699 cs
->exception_index
= POWERPC_EXCP_DLTLB
;
1702 /* Implement LRU algorithm */
1703 env
->error_code
= ctx
.key
<< 19;
1704 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1705 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1706 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1708 case POWERPC_MMU_SOFT_4xx
:
1709 case POWERPC_MMU_SOFT_4xx_Z
:
1710 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1711 env
->error_code
= 0;
1712 env
->spr
[SPR_40x_DEAR
] = address
;
1714 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1716 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1719 case POWERPC_MMU_MPC8xx
:
1721 cpu_abort(cs
, "MPC8xx MMU model is not implemented\n");
1723 case POWERPC_MMU_BOOKE206
:
1724 booke206_update_mas_tlb_miss(env
, address
, rw
, mmu_idx
);
1726 case POWERPC_MMU_BOOKE
:
1727 cs
->exception_index
= POWERPC_EXCP_DTLB
;
1728 env
->error_code
= 0;
1729 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1730 env
->spr
[SPR_BOOKE_ESR
] = mmubooke206_esr(mmu_idx
, rw
);
1732 case POWERPC_MMU_REAL
:
1733 cpu_abort(cs
, "PowerPC in real mode should never raise "
1734 "any MMU exceptions\n");
1737 cpu_abort(cs
, "Unknown or invalid MMU model\n");
1742 /* Access rights violation */
1743 cs
->exception_index
= POWERPC_EXCP_DSI
;
1744 env
->error_code
= 0;
1745 if (env
->mmu_model
== POWERPC_MMU_SOFT_4xx
1746 || env
->mmu_model
== POWERPC_MMU_SOFT_4xx_Z
) {
1747 env
->spr
[SPR_40x_DEAR
] = address
;
1749 env
->spr
[SPR_40x_ESR
] |= 0x00800000;
1751 } else if ((env
->mmu_model
== POWERPC_MMU_BOOKE
) ||
1752 (env
->mmu_model
== POWERPC_MMU_BOOKE206
)) {
1753 env
->spr
[SPR_BOOKE_DEAR
] = address
;
1754 env
->spr
[SPR_BOOKE_ESR
] = mmubooke206_esr(mmu_idx
, rw
);
1756 env
->spr
[SPR_DAR
] = address
;
1758 env
->spr
[SPR_DSISR
] = 0x0A000000;
1760 env
->spr
[SPR_DSISR
] = 0x08000000;
1765 /* Direct store exception */
1766 switch (access_type
) {
1768 /* Floating point load/store */
1769 cs
->exception_index
= POWERPC_EXCP_ALIGN
;
1770 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1771 env
->spr
[SPR_DAR
] = address
;
1774 /* lwarx, ldarx or stwcx. */
1775 cs
->exception_index
= POWERPC_EXCP_DSI
;
1776 env
->error_code
= 0;
1777 env
->spr
[SPR_DAR
] = address
;
1779 env
->spr
[SPR_DSISR
] = 0x06000000;
1781 env
->spr
[SPR_DSISR
] = 0x04000000;
1785 /* eciwx or ecowx */
1786 cs
->exception_index
= POWERPC_EXCP_DSI
;
1787 env
->error_code
= 0;
1788 env
->spr
[SPR_DAR
] = address
;
1790 env
->spr
[SPR_DSISR
] = 0x06100000;
1792 env
->spr
[SPR_DSISR
] = 0x04100000;
1796 printf("DSI: invalid exception (%d)\n", ret
);
1797 cs
->exception_index
= POWERPC_EXCP_PROGRAM
;
1799 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1800 env
->spr
[SPR_DAR
] = address
;
1812 /*****************************************************************************/
1813 /* BATs management */
1814 #if !defined(FLUSH_ALL_TLBS)
1815 static inline void do_invalidate_BAT(CPUPPCState
*env
, target_ulong BATu
,
1818 CPUState
*cs
= CPU(ppc_env_get_cpu(env
));
1819 target_ulong base
, end
, page
;
1821 base
= BATu
& ~0x0001FFFF;
1822 end
= base
+ mask
+ 0x00020000;
1823 if (((end
- base
) >> TARGET_PAGE_BITS
) > 1024) {
1824 /* Flushing 1024 4K pages is slower than a complete flush */
1825 LOG_BATS("Flush all BATs\n");
1827 LOG_BATS("Flush done\n");
1830 LOG_BATS("Flush BAT from " TARGET_FMT_lx
" to " TARGET_FMT_lx
" ("
1831 TARGET_FMT_lx
")\n", base
, end
, mask
);
1832 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
1833 tlb_flush_page(cs
, page
);
1835 LOG_BATS("Flush done\n");
1839 static inline void dump_store_bat(CPUPPCState
*env
, char ID
, int ul
, int nr
,
1842 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx
" (" TARGET_FMT_lx
")\n", ID
,
1843 nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1846 void helper_store_ibatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1849 #if defined(FLUSH_ALL_TLBS)
1850 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1853 dump_store_bat(env
, 'I', 0, nr
, value
);
1854 if (env
->IBAT
[0][nr
] != value
) {
1855 mask
= (value
<< 15) & 0x0FFE0000UL
;
1856 #if !defined(FLUSH_ALL_TLBS)
1857 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1860 * When storing valid upper BAT, mask BEPI and BRPN and
1861 * invalidate all TLBs covered by this BAT
1863 mask
= (value
<< 15) & 0x0FFE0000UL
;
1864 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1865 (value
& ~0x0001FFFFUL
& ~mask
);
1866 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1867 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1868 #if !defined(FLUSH_ALL_TLBS)
1869 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1871 tlb_flush(CPU(cpu
));
1876 void helper_store_ibatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1878 dump_store_bat(env
, 'I', 1, nr
, value
);
1879 env
->IBAT
[1][nr
] = value
;
1882 void helper_store_dbatu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1885 #if defined(FLUSH_ALL_TLBS)
1886 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1889 dump_store_bat(env
, 'D', 0, nr
, value
);
1890 if (env
->DBAT
[0][nr
] != value
) {
1892 * When storing valid upper BAT, mask BEPI and BRPN and
1893 * invalidate all TLBs covered by this BAT
1895 mask
= (value
<< 15) & 0x0FFE0000UL
;
1896 #if !defined(FLUSH_ALL_TLBS)
1897 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1899 mask
= (value
<< 15) & 0x0FFE0000UL
;
1900 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1901 (value
& ~0x0001FFFFUL
& ~mask
);
1902 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1903 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1904 #if !defined(FLUSH_ALL_TLBS)
1905 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1907 tlb_flush(CPU(cpu
));
1912 void helper_store_dbatl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1914 dump_store_bat(env
, 'D', 1, nr
, value
);
1915 env
->DBAT
[1][nr
] = value
;
1918 void helper_store_601_batu(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1921 #if defined(FLUSH_ALL_TLBS)
1922 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1926 dump_store_bat(env
, 'I', 0, nr
, value
);
1927 if (env
->IBAT
[0][nr
] != value
) {
1928 #if defined(FLUSH_ALL_TLBS)
1931 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1932 if (env
->IBAT
[1][nr
] & 0x40) {
1933 /* Invalidate BAT only if it is valid */
1934 #if !defined(FLUSH_ALL_TLBS)
1935 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1941 * When storing valid upper BAT, mask BEPI and BRPN and
1942 * invalidate all TLBs covered by this BAT
1944 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1945 (value
& ~0x0001FFFFUL
& ~mask
);
1946 env
->DBAT
[0][nr
] = env
->IBAT
[0][nr
];
1947 if (env
->IBAT
[1][nr
] & 0x40) {
1948 #if !defined(FLUSH_ALL_TLBS)
1949 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1954 #if defined(FLUSH_ALL_TLBS)
1956 tlb_flush(CPU(cpu
));
1962 void helper_store_601_batl(CPUPPCState
*env
, uint32_t nr
, target_ulong value
)
1964 #if !defined(FLUSH_ALL_TLBS)
1967 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
1971 dump_store_bat(env
, 'I', 1, nr
, value
);
1972 if (env
->IBAT
[1][nr
] != value
) {
1973 #if defined(FLUSH_ALL_TLBS)
1976 if (env
->IBAT
[1][nr
] & 0x40) {
1977 #if !defined(FLUSH_ALL_TLBS)
1978 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1979 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1985 #if !defined(FLUSH_ALL_TLBS)
1986 mask
= (value
<< 17) & 0x0FFE0000UL
;
1987 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1992 env
->IBAT
[1][nr
] = value
;
1993 env
->DBAT
[1][nr
] = value
;
1994 #if defined(FLUSH_ALL_TLBS)
1996 tlb_flush(CPU(cpu
));
2002 /*****************************************************************************/
2003 /* TLB management */
2004 void ppc_tlb_invalidate_all(CPUPPCState
*env
)
2006 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2008 #if defined(TARGET_PPC64)
2009 if (env
->mmu_model
& POWERPC_MMU_64
) {
2010 env
->tlb_need_flush
= 0;
2011 tlb_flush(CPU(cpu
));
2013 #endif /* defined(TARGET_PPC64) */
2014 switch (env
->mmu_model
) {
2015 case POWERPC_MMU_SOFT_6xx
:
2016 case POWERPC_MMU_SOFT_74xx
:
2017 ppc6xx_tlb_invalidate_all(env
);
2019 case POWERPC_MMU_SOFT_4xx
:
2020 case POWERPC_MMU_SOFT_4xx_Z
:
2021 ppc4xx_tlb_invalidate_all(env
);
2023 case POWERPC_MMU_REAL
:
2024 cpu_abort(CPU(cpu
), "No TLB for PowerPC 4xx in real mode\n");
2026 case POWERPC_MMU_MPC8xx
:
2028 cpu_abort(CPU(cpu
), "MPC8xx MMU model is not implemented\n");
2030 case POWERPC_MMU_BOOKE
:
2031 tlb_flush(CPU(cpu
));
2033 case POWERPC_MMU_BOOKE206
:
2034 booke206_flush_tlb(env
, -1, 0);
2036 case POWERPC_MMU_32B
:
2037 case POWERPC_MMU_601
:
2038 env
->tlb_need_flush
= 0;
2039 tlb_flush(CPU(cpu
));
2043 cpu_abort(CPU(cpu
), "Unknown MMU model %x\n", env
->mmu_model
);
2048 void ppc_tlb_invalidate_one(CPUPPCState
*env
, target_ulong addr
)
2050 #if !defined(FLUSH_ALL_TLBS)
2051 addr
&= TARGET_PAGE_MASK
;
2052 #if defined(TARGET_PPC64)
2053 if (env
->mmu_model
& POWERPC_MMU_64
) {
2054 /* tlbie invalidate TLBs for all segments */
2056 * XXX: given the fact that there are too many segments to invalidate,
2057 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
2058 * we just invalidate all TLBs
2060 env
->tlb_need_flush
|= TLB_NEED_LOCAL_FLUSH
;
2062 #endif /* defined(TARGET_PPC64) */
2063 switch (env
->mmu_model
) {
2064 case POWERPC_MMU_SOFT_6xx
:
2065 case POWERPC_MMU_SOFT_74xx
:
2066 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
2067 if (env
->id_tlbs
== 1) {
2068 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
2071 case POWERPC_MMU_32B
:
2072 case POWERPC_MMU_601
:
2074 * Actual CPUs invalidate entire congruence classes based on
2075 * the geometry of their TLBs and some OSes take that into
2076 * account, we just mark the TLB to be flushed later (context
2077 * synchronizing event or sync instruction on 32-bit).
2079 env
->tlb_need_flush
|= TLB_NEED_LOCAL_FLUSH
;
2082 /* Should never reach here with other MMU models */
2086 ppc_tlb_invalidate_all(env
);
2090 /*****************************************************************************/
2091 /* Special registers manipulation */
2092 void ppc_store_sdr1(CPUPPCState
*env
, target_ulong value
)
2094 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2095 qemu_log_mask(CPU_LOG_MMU
, "%s: " TARGET_FMT_lx
"\n", __func__
, value
);
2097 #if defined(TARGET_PPC64)
2098 if (env
->mmu_model
& POWERPC_MMU_64
) {
2099 target_ulong sdr_mask
= SDR_64_HTABORG
| SDR_64_HTABSIZE
;
2100 target_ulong htabsize
= value
& SDR_64_HTABSIZE
;
2102 if (value
& ~sdr_mask
) {
2103 error_report("Invalid bits 0x"TARGET_FMT_lx
" set in SDR1",
2107 if (htabsize
> 28) {
2108 error_report("Invalid HTABSIZE 0x" TARGET_FMT_lx
" stored in SDR1",
2113 #endif /* defined(TARGET_PPC64) */
2114 /* FIXME: Should check for valid HTABMASK values in 32-bit case */
2115 env
->spr
[SPR_SDR1
] = value
;
2118 #if defined(TARGET_PPC64)
2119 void ppc_store_ptcr(CPUPPCState
*env
, target_ulong value
)
2121 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2122 target_ulong ptcr_mask
= PTCR_PATB
| PTCR_PATS
;
2123 target_ulong patbsize
= value
& PTCR_PATS
;
2125 qemu_log_mask(CPU_LOG_MMU
, "%s: " TARGET_FMT_lx
"\n", __func__
, value
);
2128 assert(env
->mmu_model
& POWERPC_MMU_3_00
);
2130 if (value
& ~ptcr_mask
) {
2131 error_report("Invalid bits 0x"TARGET_FMT_lx
" set in PTCR",
2132 value
& ~ptcr_mask
);
2136 if (patbsize
> 24) {
2137 error_report("Invalid Partition Table size 0x" TARGET_FMT_lx
2138 " stored in PTCR", patbsize
);
2142 env
->spr
[SPR_PTCR
] = value
;
2145 #endif /* defined(TARGET_PPC64) */
2147 /* Segment registers load and store */
2148 target_ulong
helper_load_sr(CPUPPCState
*env
, target_ulong sr_num
)
2150 #if defined(TARGET_PPC64)
2151 if (env
->mmu_model
& POWERPC_MMU_64
) {
2156 return env
->sr
[sr_num
];
2159 void helper_store_sr(CPUPPCState
*env
, target_ulong srnum
, target_ulong value
)
2161 qemu_log_mask(CPU_LOG_MMU
,
2162 "%s: reg=%d " TARGET_FMT_lx
" " TARGET_FMT_lx
"\n", __func__
,
2163 (int)srnum
, value
, env
->sr
[srnum
]);
2164 #if defined(TARGET_PPC64)
2165 if (env
->mmu_model
& POWERPC_MMU_64
) {
2166 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2167 uint64_t esid
, vsid
;
2170 esid
= ((uint64_t)(srnum
& 0xf) << 28) | SLB_ESID_V
;
2173 vsid
= (value
& 0xfffffff) << 12;
2175 vsid
|= ((value
>> 27) & 0xf) << 8;
2177 ppc_store_slb(cpu
, srnum
, esid
, vsid
);
2180 if (env
->sr
[srnum
] != value
) {
2181 env
->sr
[srnum
] = value
;
2183 * Invalidating 256MB of virtual memory in 4kB pages is way
2184 * longer than flusing the whole TLB.
2186 #if !defined(FLUSH_ALL_TLBS) && 0
2188 target_ulong page
, end
;
2189 /* Invalidate 256 MB of virtual memory */
2190 page
= (16 << 20) * srnum
;
2191 end
= page
+ (16 << 20);
2192 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
) {
2193 tlb_flush_page(CPU(cpu
), page
);
2197 env
->tlb_need_flush
|= TLB_NEED_LOCAL_FLUSH
;
2202 /* TLB management */
2203 void helper_tlbia(CPUPPCState
*env
)
2205 ppc_tlb_invalidate_all(env
);
2208 void helper_tlbie(CPUPPCState
*env
, target_ulong addr
)
2210 ppc_tlb_invalidate_one(env
, addr
);
2213 void helper_tlbiva(CPUPPCState
*env
, target_ulong addr
)
2215 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2217 /* tlbiva instruction only exists on BookE */
2218 assert(env
->mmu_model
== POWERPC_MMU_BOOKE
);
2220 cpu_abort(CPU(cpu
), "BookE MMU model is not implemented\n");
2223 /* Software driven TLBs management */
2224 /* PowerPC 602/603 software TLB load instructions helpers */
2225 static void do_6xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2227 target_ulong RPN
, CMP
, EPN
;
2230 RPN
= env
->spr
[SPR_RPA
];
2232 CMP
= env
->spr
[SPR_ICMP
];
2233 EPN
= env
->spr
[SPR_IMISS
];
2235 CMP
= env
->spr
[SPR_DCMP
];
2236 EPN
= env
->spr
[SPR_DMISS
];
2238 way
= (env
->spr
[SPR_SRR1
] >> 17) & 1;
2239 (void)EPN
; /* avoid a compiler warning */
2240 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2241 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2243 /* Store this TLB */
2244 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2245 way
, is_code
, CMP
, RPN
);
2248 void helper_6xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2250 do_6xx_tlb(env
, EPN
, 0);
2253 void helper_6xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2255 do_6xx_tlb(env
, EPN
, 1);
2258 /* PowerPC 74xx software TLB load instructions helpers */
2259 static void do_74xx_tlb(CPUPPCState
*env
, target_ulong new_EPN
, int is_code
)
2261 target_ulong RPN
, CMP
, EPN
;
2264 RPN
= env
->spr
[SPR_PTELO
];
2265 CMP
= env
->spr
[SPR_PTEHI
];
2266 EPN
= env
->spr
[SPR_TLBMISS
] & ~0x3;
2267 way
= env
->spr
[SPR_TLBMISS
] & 0x3;
2268 (void)EPN
; /* avoid a compiler warning */
2269 LOG_SWTLB("%s: EPN " TARGET_FMT_lx
" " TARGET_FMT_lx
" PTE0 " TARGET_FMT_lx
2270 " PTE1 " TARGET_FMT_lx
" way %d\n", __func__
, new_EPN
, EPN
, CMP
,
2272 /* Store this TLB */
2273 ppc6xx_tlb_store(env
, (uint32_t)(new_EPN
& TARGET_PAGE_MASK
),
2274 way
, is_code
, CMP
, RPN
);
2277 void helper_74xx_tlbd(CPUPPCState
*env
, target_ulong EPN
)
2279 do_74xx_tlb(env
, EPN
, 0);
2282 void helper_74xx_tlbi(CPUPPCState
*env
, target_ulong EPN
)
2284 do_74xx_tlb(env
, EPN
, 1);
2287 /*****************************************************************************/
2288 /* PowerPC 601 specific instructions (POWER bridge) */
2290 target_ulong
helper_rac(CPUPPCState
*env
, target_ulong addr
)
2294 target_ulong ret
= 0;
2297 * We don't have to generate many instances of this instruction,
2298 * as rac is supervisor only.
2300 * XXX: FIX THIS: Pretend we have no BAT
2302 nb_BATs
= env
->nb_BATs
;
2304 if (get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) == 0) {
2307 env
->nb_BATs
= nb_BATs
;
2311 static inline target_ulong
booke_tlb_to_page_size(int size
)
2313 return 1024 << (2 * size
);
2316 static inline int booke_page_size_to_tlb(target_ulong page_size
)
2320 switch (page_size
) {
2354 #if defined(TARGET_PPC64)
2355 case 0x000100000000ULL
:
2358 case 0x000400000000ULL
:
2361 case 0x001000000000ULL
:
2364 case 0x004000000000ULL
:
2367 case 0x010000000000ULL
:
2379 /* Helpers for 4xx TLB management */
2380 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2382 #define PPC4XX_TLBHI_V 0x00000040
2383 #define PPC4XX_TLBHI_E 0x00000020
2384 #define PPC4XX_TLBHI_SIZE_MIN 0
2385 #define PPC4XX_TLBHI_SIZE_MAX 7
2386 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2387 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2388 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2390 #define PPC4XX_TLBLO_EX 0x00000200
2391 #define PPC4XX_TLBLO_WR 0x00000100
2392 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2393 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2395 target_ulong
helper_4xx_tlbre_hi(CPUPPCState
*env
, target_ulong entry
)
2401 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2402 tlb
= &env
->tlb
.tlbe
[entry
];
2404 if (tlb
->prot
& PAGE_VALID
) {
2405 ret
|= PPC4XX_TLBHI_V
;
2407 size
= booke_page_size_to_tlb(tlb
->size
);
2408 if (size
< PPC4XX_TLBHI_SIZE_MIN
|| size
> PPC4XX_TLBHI_SIZE_MAX
) {
2409 size
= PPC4XX_TLBHI_SIZE_DEFAULT
;
2411 ret
|= size
<< PPC4XX_TLBHI_SIZE_SHIFT
;
2412 env
->spr
[SPR_40x_PID
] = tlb
->PID
;
2416 target_ulong
helper_4xx_tlbre_lo(CPUPPCState
*env
, target_ulong entry
)
2421 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2422 tlb
= &env
->tlb
.tlbe
[entry
];
2424 if (tlb
->prot
& PAGE_EXEC
) {
2425 ret
|= PPC4XX_TLBLO_EX
;
2427 if (tlb
->prot
& PAGE_WRITE
) {
2428 ret
|= PPC4XX_TLBLO_WR
;
2433 void helper_4xx_tlbwe_hi(CPUPPCState
*env
, target_ulong entry
,
2436 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2437 CPUState
*cs
= CPU(cpu
);
2439 target_ulong page
, end
;
2441 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2443 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2444 tlb
= &env
->tlb
.tlbe
[entry
];
2445 /* Invalidate previous TLB (if it's valid) */
2446 if (tlb
->prot
& PAGE_VALID
) {
2447 end
= tlb
->EPN
+ tlb
->size
;
2448 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx
" end "
2449 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2450 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2451 tlb_flush_page(cs
, page
);
2454 tlb
->size
= booke_tlb_to_page_size((val
>> PPC4XX_TLBHI_SIZE_SHIFT
)
2455 & PPC4XX_TLBHI_SIZE_MASK
);
2457 * We cannot handle TLB size < TARGET_PAGE_SIZE.
2458 * If this ever occurs, we should implement TARGET_PAGE_BITS_VARY
2460 if ((val
& PPC4XX_TLBHI_V
) && tlb
->size
< TARGET_PAGE_SIZE
) {
2461 cpu_abort(cs
, "TLB size " TARGET_FMT_lu
" < %u "
2462 "are not supported (%d)\n"
2463 "Please implement TARGET_PAGE_BITS_VARY\n",
2464 tlb
->size
, TARGET_PAGE_SIZE
, (int)((val
>> 7) & 0x7));
2466 tlb
->EPN
= val
& ~(tlb
->size
- 1);
2467 if (val
& PPC4XX_TLBHI_V
) {
2468 tlb
->prot
|= PAGE_VALID
;
2469 if (val
& PPC4XX_TLBHI_E
) {
2470 /* XXX: TO BE FIXED */
2472 "Little-endian TLB entries are not supported by now\n");
2475 tlb
->prot
&= ~PAGE_VALID
;
2477 tlb
->PID
= env
->spr
[SPR_40x_PID
]; /* PID */
2478 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2479 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2480 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2481 tlb
->prot
& PAGE_READ
? 'r' : '-',
2482 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2483 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2484 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2485 /* Invalidate new TLB (if valid) */
2486 if (tlb
->prot
& PAGE_VALID
) {
2487 end
= tlb
->EPN
+ tlb
->size
;
2488 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx
" end "
2489 TARGET_FMT_lx
"\n", __func__
, (int)entry
, tlb
->EPN
, end
);
2490 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
) {
2491 tlb_flush_page(cs
, page
);
2496 void helper_4xx_tlbwe_lo(CPUPPCState
*env
, target_ulong entry
,
2501 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx
"\n", __func__
, (int)entry
,
2503 entry
&= PPC4XX_TLB_ENTRY_MASK
;
2504 tlb
= &env
->tlb
.tlbe
[entry
];
2505 tlb
->attr
= val
& PPC4XX_TLBLO_ATTR_MASK
;
2506 tlb
->RPN
= val
& PPC4XX_TLBLO_RPN_MASK
;
2507 tlb
->prot
= PAGE_READ
;
2508 if (val
& PPC4XX_TLBLO_EX
) {
2509 tlb
->prot
|= PAGE_EXEC
;
2511 if (val
& PPC4XX_TLBLO_WR
) {
2512 tlb
->prot
|= PAGE_WRITE
;
2514 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx
" EPN " TARGET_FMT_lx
2515 " size " TARGET_FMT_lx
" prot %c%c%c%c PID %d\n", __func__
,
2516 (int)entry
, tlb
->RPN
, tlb
->EPN
, tlb
->size
,
2517 tlb
->prot
& PAGE_READ
? 'r' : '-',
2518 tlb
->prot
& PAGE_WRITE
? 'w' : '-',
2519 tlb
->prot
& PAGE_EXEC
? 'x' : '-',
2520 tlb
->prot
& PAGE_VALID
? 'v' : '-', (int)tlb
->PID
);
2523 target_ulong
helper_4xx_tlbsx(CPUPPCState
*env
, target_ulong address
)
2525 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_40x_PID
]);
2528 /* PowerPC 440 TLB management */
2529 void helper_440_tlbwe(CPUPPCState
*env
, uint32_t word
, target_ulong entry
,
2532 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2534 target_ulong EPN
, RPN
, size
;
2537 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx
"\n",
2538 __func__
, word
, (int)entry
, value
);
2541 tlb
= &env
->tlb
.tlbe
[entry
];
2544 /* Just here to please gcc */
2546 EPN
= value
& 0xFFFFFC00;
2547 if ((tlb
->prot
& PAGE_VALID
) && EPN
!= tlb
->EPN
) {
2551 size
= booke_tlb_to_page_size((value
>> 4) & 0xF);
2552 if ((tlb
->prot
& PAGE_VALID
) && tlb
->size
< size
) {
2557 tlb
->attr
|= (value
>> 8) & 1;
2558 if (value
& 0x200) {
2559 tlb
->prot
|= PAGE_VALID
;
2561 if (tlb
->prot
& PAGE_VALID
) {
2562 tlb
->prot
&= ~PAGE_VALID
;
2566 tlb
->PID
= env
->spr
[SPR_440_MMUCR
] & 0x000000FF;
2567 if (do_flush_tlbs
) {
2568 tlb_flush(CPU(cpu
));
2572 RPN
= value
& 0xFFFFFC0F;
2573 if ((tlb
->prot
& PAGE_VALID
) && tlb
->RPN
!= RPN
) {
2574 tlb_flush(CPU(cpu
));
2579 tlb
->attr
= (tlb
->attr
& 0x1) | (value
& 0x0000FF00);
2580 tlb
->prot
= tlb
->prot
& PAGE_VALID
;
2582 tlb
->prot
|= PAGE_READ
<< 4;
2585 tlb
->prot
|= PAGE_WRITE
<< 4;
2588 tlb
->prot
|= PAGE_EXEC
<< 4;
2591 tlb
->prot
|= PAGE_READ
;
2594 tlb
->prot
|= PAGE_WRITE
;
2597 tlb
->prot
|= PAGE_EXEC
;
2603 target_ulong
helper_440_tlbre(CPUPPCState
*env
, uint32_t word
,
2611 tlb
= &env
->tlb
.tlbe
[entry
];
2614 /* Just here to please gcc */
2617 size
= booke_page_size_to_tlb(tlb
->size
);
2618 if (size
< 0 || size
> 0xF) {
2622 if (tlb
->attr
& 0x1) {
2625 if (tlb
->prot
& PAGE_VALID
) {
2628 env
->spr
[SPR_440_MMUCR
] &= ~0x000000FF;
2629 env
->spr
[SPR_440_MMUCR
] |= tlb
->PID
;
2635 ret
= tlb
->attr
& ~0x1;
2636 if (tlb
->prot
& (PAGE_READ
<< 4)) {
2639 if (tlb
->prot
& (PAGE_WRITE
<< 4)) {
2642 if (tlb
->prot
& (PAGE_EXEC
<< 4)) {
2645 if (tlb
->prot
& PAGE_READ
) {
2648 if (tlb
->prot
& PAGE_WRITE
) {
2651 if (tlb
->prot
& PAGE_EXEC
) {
2659 target_ulong
helper_440_tlbsx(CPUPPCState
*env
, target_ulong address
)
2661 return ppcemb_tlb_search(env
, address
, env
->spr
[SPR_440_MMUCR
] & 0xFF);
2664 /* PowerPC BookE 2.06 TLB management */
2666 static ppcmas_tlb_t
*booke206_cur_tlb(CPUPPCState
*env
)
2668 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2669 uint32_t tlbncfg
= 0;
2670 int esel
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ESEL_MASK
) >> MAS0_ESEL_SHIFT
;
2671 int ea
= (env
->spr
[SPR_BOOKE_MAS2
] & MAS2_EPN_MASK
);
2674 tlb
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2675 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlb
];
2677 if ((tlbncfg
& TLBnCFG_HES
) && (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_HES
)) {
2678 cpu_abort(CPU(cpu
), "we don't support HES yet\n");
2681 return booke206_get_tlbm(env
, tlb
, ea
, esel
);
2684 void helper_booke_setpid(CPUPPCState
*env
, uint32_t pidn
, target_ulong pid
)
2686 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2688 env
->spr
[pidn
] = pid
;
2689 /* changing PIDs mean we're in a different address space now */
2690 tlb_flush(CPU(cpu
));
2693 void helper_booke_set_eplc(CPUPPCState
*env
, target_ulong val
)
2695 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2696 env
->spr
[SPR_BOOKE_EPLC
] = val
& EPID_MASK
;
2697 tlb_flush_by_mmuidx(CPU(cpu
), 1 << PPC_TLB_EPID_LOAD
);
2699 void helper_booke_set_epsc(CPUPPCState
*env
, target_ulong val
)
2701 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2702 env
->spr
[SPR_BOOKE_EPSC
] = val
& EPID_MASK
;
2703 tlb_flush_by_mmuidx(CPU(cpu
), 1 << PPC_TLB_EPID_STORE
);
2706 static inline void flush_page(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2708 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2710 if (booke206_tlb_to_page_size(env
, tlb
) == TARGET_PAGE_SIZE
) {
2711 tlb_flush_page(CPU(cpu
), tlb
->mas2
& MAS2_EPN_MASK
);
2713 tlb_flush(CPU(cpu
));
2717 void helper_booke206_tlbwe(CPUPPCState
*env
)
2719 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2720 uint32_t tlbncfg
, tlbn
;
2722 uint32_t size_tlb
, size_ps
;
2726 switch (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_WQ_MASK
) {
2727 case MAS0_WQ_ALWAYS
:
2728 /* good to go, write that entry */
2731 /* XXX check if reserved */
2736 case MAS0_WQ_CLR_RSRV
:
2737 /* XXX clear entry */
2740 /* no idea what to do */
2744 if (((env
->spr
[SPR_BOOKE_MAS0
] & MAS0_ATSEL
) == MAS0_ATSEL_LRAT
) &&
2746 /* XXX we don't support direct LRAT setting yet */
2747 fprintf(stderr
, "cpu: don't support LRAT setting yet\n");
2751 tlbn
= (env
->spr
[SPR_BOOKE_MAS0
] & MAS0_TLBSEL_MASK
) >> MAS0_TLBSEL_SHIFT
;
2752 tlbncfg
= env
->spr
[SPR_BOOKE_TLB0CFG
+ tlbn
];
2754 tlb
= booke206_cur_tlb(env
);
2757 raise_exception_err_ra(env
, POWERPC_EXCP_PROGRAM
,
2758 POWERPC_EXCP_INVAL
|
2759 POWERPC_EXCP_INVAL_INVAL
, GETPC());
2762 /* check that we support the targeted size */
2763 size_tlb
= (env
->spr
[SPR_BOOKE_MAS1
] & MAS1_TSIZE_MASK
) >> MAS1_TSIZE_SHIFT
;
2764 size_ps
= booke206_tlbnps(env
, tlbn
);
2765 if ((env
->spr
[SPR_BOOKE_MAS1
] & MAS1_VALID
) && (tlbncfg
& TLBnCFG_AVAIL
) &&
2766 !(size_ps
& (1 << size_tlb
))) {
2767 raise_exception_err_ra(env
, POWERPC_EXCP_PROGRAM
,
2768 POWERPC_EXCP_INVAL
|
2769 POWERPC_EXCP_INVAL_INVAL
, GETPC());
2773 cpu_abort(CPU(cpu
), "missing HV implementation\n");
2776 if (tlb
->mas1
& MAS1_VALID
) {
2778 * Invalidate the page in QEMU TLB if it was a valid entry.
2780 * In "PowerPC e500 Core Family Reference Manual, Rev. 1",
2781 * Section "12.4.2 TLB Write Entry (tlbwe) Instruction":
2782 * (https://www.nxp.com/docs/en/reference-manual/E500CORERM.pdf)
2784 * "Note that when an L2 TLB entry is written, it may be displacing an
2785 * already valid entry in the same L2 TLB location (a victim). If a
2786 * valid L1 TLB entry corresponds to the L2 MMU victim entry, that L1
2787 * TLB entry is automatically invalidated."
2789 flush_page(env
, tlb
);
2792 tlb
->mas7_3
= ((uint64_t)env
->spr
[SPR_BOOKE_MAS7
] << 32) |
2793 env
->spr
[SPR_BOOKE_MAS3
];
2794 tlb
->mas1
= env
->spr
[SPR_BOOKE_MAS1
];
2796 if ((env
->spr
[SPR_MMUCFG
] & MMUCFG_MAVN
) == MMUCFG_MAVN_V2
) {
2797 /* For TLB which has a fixed size TSIZE is ignored with MAV2 */
2798 booke206_fixed_size_tlbn(env
, tlbn
, tlb
);
2800 if (!(tlbncfg
& TLBnCFG_AVAIL
)) {
2801 /* force !AVAIL TLB entries to correct page size */
2802 tlb
->mas1
&= ~MAS1_TSIZE_MASK
;
2803 /* XXX can be configured in MMUCSR0 */
2804 tlb
->mas1
|= (tlbncfg
& TLBnCFG_MINSIZE
) >> 12;
2808 /* Make a mask from TLB size to discard invalid bits in EPN field */
2809 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2810 /* Add a mask for page attributes */
2811 mask
|= MAS2_ACM
| MAS2_VLE
| MAS2_W
| MAS2_I
| MAS2_M
| MAS2_G
| MAS2_E
;
2815 * Executing a tlbwe instruction in 32-bit mode will set bits
2816 * 0:31 of the TLB EPN field to zero.
2821 tlb
->mas2
= env
->spr
[SPR_BOOKE_MAS2
] & mask
;
2823 if (!(tlbncfg
& TLBnCFG_IPROT
)) {
2824 /* no IPROT supported by TLB */
2825 tlb
->mas1
&= ~MAS1_IPROT
;
2828 flush_page(env
, tlb
);
2831 static inline void booke206_tlb_to_mas(CPUPPCState
*env
, ppcmas_tlb_t
*tlb
)
2833 int tlbn
= booke206_tlbm_to_tlbn(env
, tlb
);
2834 int way
= booke206_tlbm_to_way(env
, tlb
);
2836 env
->spr
[SPR_BOOKE_MAS0
] = tlbn
<< MAS0_TLBSEL_SHIFT
;
2837 env
->spr
[SPR_BOOKE_MAS0
] |= way
<< MAS0_ESEL_SHIFT
;
2838 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2840 env
->spr
[SPR_BOOKE_MAS1
] = tlb
->mas1
;
2841 env
->spr
[SPR_BOOKE_MAS2
] = tlb
->mas2
;
2842 env
->spr
[SPR_BOOKE_MAS3
] = tlb
->mas7_3
;
2843 env
->spr
[SPR_BOOKE_MAS7
] = tlb
->mas7_3
>> 32;
2846 void helper_booke206_tlbre(CPUPPCState
*env
)
2848 ppcmas_tlb_t
*tlb
= NULL
;
2850 tlb
= booke206_cur_tlb(env
);
2852 env
->spr
[SPR_BOOKE_MAS1
] = 0;
2854 booke206_tlb_to_mas(env
, tlb
);
2858 void helper_booke206_tlbsx(CPUPPCState
*env
, target_ulong address
)
2860 ppcmas_tlb_t
*tlb
= NULL
;
2865 spid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID_MASK
) >> MAS6_SPID_SHIFT
;
2866 sas
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
;
2868 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2869 int ways
= booke206_tlb_ways(env
, i
);
2871 for (j
= 0; j
< ways
; j
++) {
2872 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
2878 if (ppcmas_tlb_check(env
, tlb
, &raddr
, address
, spid
)) {
2882 if (sas
!= ((tlb
->mas1
& MAS1_TS
) >> MAS1_TS_SHIFT
)) {
2886 booke206_tlb_to_mas(env
, tlb
);
2891 /* no entry found, fill with defaults */
2892 env
->spr
[SPR_BOOKE_MAS0
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TLBSELD_MASK
;
2893 env
->spr
[SPR_BOOKE_MAS1
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_TSIZED_MASK
;
2894 env
->spr
[SPR_BOOKE_MAS2
] = env
->spr
[SPR_BOOKE_MAS4
] & MAS4_WIMGED_MASK
;
2895 env
->spr
[SPR_BOOKE_MAS3
] = 0;
2896 env
->spr
[SPR_BOOKE_MAS7
] = 0;
2898 if (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SAS
) {
2899 env
->spr
[SPR_BOOKE_MAS1
] |= MAS1_TS
;
2902 env
->spr
[SPR_BOOKE_MAS1
] |= (env
->spr
[SPR_BOOKE_MAS6
] >> 16)
2905 /* next victim logic */
2906 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_ESEL_SHIFT
;
2908 env
->last_way
&= booke206_tlb_ways(env
, 0) - 1;
2909 env
->spr
[SPR_BOOKE_MAS0
] |= env
->last_way
<< MAS0_NV_SHIFT
;
2912 static inline void booke206_invalidate_ea_tlb(CPUPPCState
*env
, int tlbn
,
2916 int ways
= booke206_tlb_ways(env
, tlbn
);
2919 for (i
= 0; i
< ways
; i
++) {
2920 ppcmas_tlb_t
*tlb
= booke206_get_tlbm(env
, tlbn
, ea
, i
);
2924 mask
= ~(booke206_tlb_to_page_size(env
, tlb
) - 1);
2925 if (((tlb
->mas2
& MAS2_EPN_MASK
) == (ea
& mask
)) &&
2926 !(tlb
->mas1
& MAS1_IPROT
)) {
2927 tlb
->mas1
&= ~MAS1_VALID
;
2932 void helper_booke206_tlbivax(CPUPPCState
*env
, target_ulong address
)
2936 if (address
& 0x4) {
2937 /* flush all entries */
2938 if (address
& 0x8) {
2939 /* flush all of TLB1 */
2940 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB1
, 1);
2942 /* flush all of TLB0 */
2943 booke206_flush_tlb(env
, BOOKE206_FLUSH_TLB0
, 0);
2948 if (address
& 0x8) {
2949 /* flush TLB1 entries */
2950 booke206_invalidate_ea_tlb(env
, 1, address
);
2955 /* flush TLB0 entries */
2956 booke206_invalidate_ea_tlb(env
, 0, address
);
2958 tlb_flush_page(cs
, address
& MAS2_EPN_MASK
);
2963 void helper_booke206_tlbilx0(CPUPPCState
*env
, target_ulong address
)
2965 /* XXX missing LPID handling */
2966 booke206_flush_tlb(env
, -1, 1);
2969 void helper_booke206_tlbilx1(CPUPPCState
*env
, target_ulong address
)
2971 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2973 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2974 ppcmas_tlb_t
*tlb
= env
->tlb
.tlbm
;
2977 /* XXX missing LPID handling */
2978 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
2979 tlb_size
= booke206_tlb_size(env
, i
);
2980 for (j
= 0; j
< tlb_size
; j
++) {
2981 if (!(tlb
[j
].mas1
& MAS1_IPROT
) &&
2982 ((tlb
[j
].mas1
& MAS1_TID_MASK
) == tid
)) {
2983 tlb
[j
].mas1
&= ~MAS1_VALID
;
2986 tlb
+= booke206_tlb_size(env
, i
);
2988 tlb_flush(CPU(cpu
));
2991 void helper_booke206_tlbilx3(CPUPPCState
*env
, target_ulong address
)
2993 PowerPCCPU
*cpu
= ppc_env_get_cpu(env
);
2996 int tid
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SPID
);
2997 int pid
= tid
>> MAS6_SPID_SHIFT
;
2998 int sgs
= env
->spr
[SPR_BOOKE_MAS5
] & MAS5_SGS
;
2999 int ind
= (env
->spr
[SPR_BOOKE_MAS6
] & MAS6_SIND
) ? MAS1_IND
: 0;
3000 /* XXX check for unsupported isize and raise an invalid opcode then */
3001 int size
= env
->spr
[SPR_BOOKE_MAS6
] & MAS6_ISIZE_MASK
;
3002 /* XXX implement MAV2 handling */
3005 /* XXX missing LPID handling */
3006 /* flush by pid and ea */
3007 for (i
= 0; i
< BOOKE206_MAX_TLBN
; i
++) {
3008 int ways
= booke206_tlb_ways(env
, i
);
3010 for (j
= 0; j
< ways
; j
++) {
3011 tlb
= booke206_get_tlbm(env
, i
, address
, j
);
3015 if ((ppcmas_tlb_check(env
, tlb
, NULL
, address
, pid
) != 0) ||
3016 (tlb
->mas1
& MAS1_IPROT
) ||
3017 ((tlb
->mas1
& MAS1_IND
) != ind
) ||
3018 ((tlb
->mas8
& MAS8_TGS
) != sgs
)) {
3021 if (mav2
&& ((tlb
->mas1
& MAS1_TSIZE_MASK
) != size
)) {
3022 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
3025 /* XXX e500mc doesn't match SAS, but other cores might */
3026 tlb
->mas1
&= ~MAS1_VALID
;
3029 tlb_flush(CPU(cpu
));
3032 void helper_booke206_tlbflush(CPUPPCState
*env
, target_ulong type
)
3037 flags
|= BOOKE206_FLUSH_TLB1
;
3041 flags
|= BOOKE206_FLUSH_TLB0
;
3044 booke206_flush_tlb(env
, flags
, 1);
3048 void helper_check_tlb_flush_local(CPUPPCState
*env
)
3050 check_tlb_flush(env
, false);
3053 void helper_check_tlb_flush_global(CPUPPCState
*env
)
3055 check_tlb_flush(env
, true);
3058 /*****************************************************************************/
3061 * try to fill the TLB and return an exception if error. If retaddr is
3062 * NULL, it means that the function was called in C code (i.e. not
3063 * from generated code or from helper.c)
3065 * XXX: fix it to restore all registers
3067 void tlb_fill(CPUState
*cs
, target_ulong addr
, int size
,
3068 MMUAccessType access_type
, int mmu_idx
, uintptr_t retaddr
)
3070 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
3071 PowerPCCPUClass
*pcc
= POWERPC_CPU_GET_CLASS(cs
);
3072 CPUPPCState
*env
= &cpu
->env
;
3075 if (pcc
->handle_mmu_fault
) {
3076 ret
= pcc
->handle_mmu_fault(cpu
, addr
, access_type
, mmu_idx
);
3078 ret
= cpu_ppc_handle_mmu_fault(env
, addr
, access_type
, mmu_idx
);
3080 if (unlikely(ret
!= 0)) {
3081 raise_exception_err_ra(env
, cs
->exception_index
, env
->error_code
,