2 * PowerPC 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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "helper_regs.h"
31 #include "qemu-common.h"
37 //#define DEBUG_SOFTWARE_TLB
38 //#define DUMP_PAGE_TABLES
39 //#define DEBUG_EXCEPTIONS
40 //#define FLUSH_ALL_TLBS
42 /*****************************************************************************/
43 /* Exceptions processing */
45 void raise_exception_err (CPUState
*env
, int exception
, int error_code
)
48 printf("Raise exception %3x code : %d\n", exception
, error_code
);
50 env
->exception_index
= exception
;
51 env
->error_code
= error_code
;
55 void raise_exception (CPUState
*env
, int exception
)
57 helper_raise_exception_err(exception
, 0);
60 /*****************************************************************************/
61 /* PowerPC MMU emulation */
63 #if defined(CONFIG_USER_ONLY)
64 int cpu_ppc_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
65 int mmu_idx
, int is_softmmu
)
67 int exception
, error_code
;
70 exception
= POWERPC_EXCP_ISI
;
71 error_code
= 0x40000000;
73 exception
= POWERPC_EXCP_DSI
;
74 error_code
= 0x40000000;
76 error_code
|= 0x02000000;
77 env
->spr
[SPR_DAR
] = address
;
78 env
->spr
[SPR_DSISR
] = error_code
;
80 env
->exception_index
= exception
;
81 env
->error_code
= error_code
;
86 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
92 /* Common routines used by software and hardware TLBs emulation */
93 static always_inline
int pte_is_valid (target_ulong pte0
)
95 return pte0
& 0x80000000 ? 1 : 0;
98 static always_inline
void pte_invalidate (target_ulong
*pte0
)
100 *pte0
&= ~0x80000000;
103 #if defined(TARGET_PPC64)
104 static always_inline
int pte64_is_valid (target_ulong pte0
)
106 return pte0
& 0x0000000000000001ULL
? 1 : 0;
109 static always_inline
void pte64_invalidate (target_ulong
*pte0
)
111 *pte0
&= ~0x0000000000000001ULL
;
115 #define PTE_PTEM_MASK 0x7FFFFFBF
116 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
117 #if defined(TARGET_PPC64)
118 #define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
119 #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
122 static always_inline
int pp_check (int key
, int pp
, int nx
)
126 /* Compute access rights */
127 /* When pp is 3/7, the result is undefined. Set it to noaccess */
134 access
|= PAGE_WRITE
;
152 access
= PAGE_READ
| PAGE_WRITE
;
162 static always_inline
int check_prot (int prot
, int rw
, int access_type
)
166 if (access_type
== ACCESS_CODE
) {
167 if (prot
& PAGE_EXEC
)
172 if (prot
& PAGE_WRITE
)
177 if (prot
& PAGE_READ
)
186 static always_inline
int _pte_check (mmu_ctx_t
*ctx
, int is_64b
,
187 target_ulong pte0
, target_ulong pte1
,
188 int h
, int rw
, int type
)
190 target_ulong ptem
, mmask
;
191 int access
, ret
, pteh
, ptev
, pp
;
195 /* Check validity and table match */
196 #if defined(TARGET_PPC64)
198 ptev
= pte64_is_valid(pte0
);
199 pteh
= (pte0
>> 1) & 1;
203 ptev
= pte_is_valid(pte0
);
204 pteh
= (pte0
>> 6) & 1;
206 if (ptev
&& h
== pteh
) {
207 /* Check vsid & api */
208 #if defined(TARGET_PPC64)
210 ptem
= pte0
& PTE64_PTEM_MASK
;
211 mmask
= PTE64_CHECK_MASK
;
212 pp
= (pte1
& 0x00000003) | ((pte1
>> 61) & 0x00000004);
213 ctx
->nx
|= (pte1
>> 2) & 1; /* No execute bit */
214 ctx
->nx
|= (pte1
>> 3) & 1; /* Guarded bit */
218 ptem
= pte0
& PTE_PTEM_MASK
;
219 mmask
= PTE_CHECK_MASK
;
220 pp
= pte1
& 0x00000003;
222 if (ptem
== ctx
->ptem
) {
223 if (ctx
->raddr
!= (target_phys_addr_t
)-1ULL) {
224 /* all matches should have equal RPN, WIMG & PP */
225 if ((ctx
->raddr
& mmask
) != (pte1
& mmask
)) {
227 fprintf(logfile
, "Bad RPN/WIMG/PP\n");
231 /* Compute access rights */
232 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
233 /* Keep the matching PTE informations */
236 ret
= check_prot(ctx
->prot
, rw
, type
);
239 #if defined (DEBUG_MMU)
241 fprintf(logfile
, "PTE access granted !\n");
244 /* Access right violation */
245 #if defined (DEBUG_MMU)
247 fprintf(logfile
, "PTE access rejected\n");
256 static always_inline
int pte32_check (mmu_ctx_t
*ctx
,
257 target_ulong pte0
, target_ulong pte1
,
258 int h
, int rw
, int type
)
260 return _pte_check(ctx
, 0, pte0
, pte1
, h
, rw
, type
);
263 #if defined(TARGET_PPC64)
264 static always_inline
int pte64_check (mmu_ctx_t
*ctx
,
265 target_ulong pte0
, target_ulong pte1
,
266 int h
, int rw
, int type
)
268 return _pte_check(ctx
, 1, pte0
, pte1
, h
, rw
, type
);
272 static always_inline
int pte_update_flags (mmu_ctx_t
*ctx
, target_ulong
*pte1p
,
277 /* Update page flags */
278 if (!(*pte1p
& 0x00000100)) {
279 /* Update accessed flag */
280 *pte1p
|= 0x00000100;
283 if (!(*pte1p
& 0x00000080)) {
284 if (rw
== 1 && ret
== 0) {
285 /* Update changed flag */
286 *pte1p
|= 0x00000080;
289 /* Force page fault for first write access */
290 ctx
->prot
&= ~PAGE_WRITE
;
297 /* Software driven TLB helpers */
298 static always_inline
int ppc6xx_tlb_getnum (CPUState
*env
, target_ulong eaddr
,
299 int way
, int is_code
)
303 /* Select TLB num in a way from address */
304 nr
= (eaddr
>> TARGET_PAGE_BITS
) & (env
->tlb_per_way
- 1);
306 nr
+= env
->tlb_per_way
* way
;
307 /* 6xx have separate TLBs for instructions and data */
308 if (is_code
&& env
->id_tlbs
== 1)
314 static always_inline
void ppc6xx_tlb_invalidate_all (CPUState
*env
)
319 #if defined (DEBUG_SOFTWARE_TLB) && 0
321 fprintf(logfile
, "Invalidate all TLBs\n");
324 /* Invalidate all defined software TLB */
326 if (env
->id_tlbs
== 1)
328 for (nr
= 0; nr
< max
; nr
++) {
329 tlb
= &env
->tlb
[nr
].tlb6
;
330 pte_invalidate(&tlb
->pte0
);
335 static always_inline
void __ppc6xx_tlb_invalidate_virt (CPUState
*env
,
340 #if !defined(FLUSH_ALL_TLBS)
344 /* Invalidate ITLB + DTLB, all ways */
345 for (way
= 0; way
< env
->nb_ways
; way
++) {
346 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
, is_code
);
347 tlb
= &env
->tlb
[nr
].tlb6
;
348 if (pte_is_valid(tlb
->pte0
) && (match_epn
== 0 || eaddr
== tlb
->EPN
)) {
349 #if defined (DEBUG_SOFTWARE_TLB)
351 fprintf(logfile
, "TLB invalidate %d/%d " ADDRX
"\n",
352 nr
, env
->nb_tlb
, eaddr
);
355 pte_invalidate(&tlb
->pte0
);
356 tlb_flush_page(env
, tlb
->EPN
);
360 /* XXX: PowerPC specification say this is valid as well */
361 ppc6xx_tlb_invalidate_all(env
);
365 static always_inline
void ppc6xx_tlb_invalidate_virt (CPUState
*env
,
369 __ppc6xx_tlb_invalidate_virt(env
, eaddr
, is_code
, 0);
372 void ppc6xx_tlb_store (CPUState
*env
, target_ulong EPN
, int way
, int is_code
,
373 target_ulong pte0
, target_ulong pte1
)
378 nr
= ppc6xx_tlb_getnum(env
, EPN
, way
, is_code
);
379 tlb
= &env
->tlb
[nr
].tlb6
;
380 #if defined (DEBUG_SOFTWARE_TLB)
382 fprintf(logfile
, "Set TLB %d/%d EPN " ADDRX
" PTE0 " ADDRX
383 " PTE1 " ADDRX
"\n", nr
, env
->nb_tlb
, EPN
, pte0
, pte1
);
386 /* Invalidate any pending reference in Qemu for this virtual address */
387 __ppc6xx_tlb_invalidate_virt(env
, EPN
, is_code
, 1);
391 /* Store last way for LRU mechanism */
395 static always_inline
int ppc6xx_tlb_check (CPUState
*env
, mmu_ctx_t
*ctx
,
396 target_ulong eaddr
, int rw
,
404 ret
= -1; /* No TLB found */
405 for (way
= 0; way
< env
->nb_ways
; way
++) {
406 nr
= ppc6xx_tlb_getnum(env
, eaddr
, way
,
407 access_type
== ACCESS_CODE
? 1 : 0);
408 tlb
= &env
->tlb
[nr
].tlb6
;
409 /* This test "emulates" the PTE index match for hardware TLBs */
410 if ((eaddr
& TARGET_PAGE_MASK
) != tlb
->EPN
) {
411 #if defined (DEBUG_SOFTWARE_TLB)
413 fprintf(logfile
, "TLB %d/%d %s [" ADDRX
" " ADDRX
416 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
417 tlb
->EPN
, tlb
->EPN
+ TARGET_PAGE_SIZE
, eaddr
);
422 #if defined (DEBUG_SOFTWARE_TLB)
424 fprintf(logfile
, "TLB %d/%d %s " ADDRX
" <> " ADDRX
" " ADDRX
427 pte_is_valid(tlb
->pte0
) ? "valid" : "inval",
428 tlb
->EPN
, eaddr
, tlb
->pte1
,
429 rw
? 'S' : 'L', access_type
== ACCESS_CODE
? 'I' : 'D');
432 switch (pte32_check(ctx
, tlb
->pte0
, tlb
->pte1
, 0, rw
, access_type
)) {
434 /* TLB inconsistency */
437 /* Access violation */
447 /* XXX: we should go on looping to check all TLBs consistency
448 * but we can speed-up the whole thing as the
449 * result would be undefined if TLBs are not consistent.
458 #if defined (DEBUG_SOFTWARE_TLB)
460 fprintf(logfile
, "found TLB at addr " PADDRX
" prot=%01x ret=%d\n",
461 ctx
->raddr
& TARGET_PAGE_MASK
, ctx
->prot
, ret
);
464 /* Update page flags */
465 pte_update_flags(ctx
, &env
->tlb
[best
].tlb6
.pte1
, ret
, rw
);
471 /* Perform BAT hit & translation */
472 static always_inline
void bat_size_prot (CPUState
*env
, target_ulong
*blp
,
473 int *validp
, int *protp
,
474 target_ulong
*BATu
, target_ulong
*BATl
)
479 bl
= (*BATu
& 0x00001FFC) << 15;
482 if (((msr_pr
== 0) && (*BATu
& 0x00000002)) ||
483 ((msr_pr
!= 0) && (*BATu
& 0x00000001))) {
485 pp
= *BATl
& 0x00000003;
487 prot
= PAGE_READ
| PAGE_EXEC
;
497 static always_inline
void bat_601_size_prot (CPUState
*env
,target_ulong
*blp
,
498 int *validp
, int *protp
,
503 int key
, pp
, valid
, prot
;
505 bl
= (*BATl
& 0x0000003F) << 17;
506 #if defined (DEBUG_BATS)
508 fprintf(logfile
, "b %02x ==> bl " ADDRX
" msk " ADDRX
"\n",
509 (uint8_t)(*BATl
& 0x0000003F), bl
, ~bl
);
513 valid
= (*BATl
>> 6) & 1;
515 pp
= *BATu
& 0x00000003;
517 key
= (*BATu
>> 3) & 1;
519 key
= (*BATu
>> 2) & 1;
520 prot
= pp_check(key
, pp
, 0);
527 static always_inline
int get_bat (CPUState
*env
, mmu_ctx_t
*ctx
,
528 target_ulong
virtual, int rw
, int type
)
530 target_ulong
*BATlt
, *BATut
, *BATu
, *BATl
;
531 target_ulong base
, BEPIl
, BEPIu
, bl
;
535 #if defined (DEBUG_BATS)
537 fprintf(logfile
, "%s: %cBAT v " ADDRX
"\n", __func__
,
538 type
== ACCESS_CODE
? 'I' : 'D', virtual);
543 BATlt
= env
->IBAT
[1];
544 BATut
= env
->IBAT
[0];
547 BATlt
= env
->DBAT
[1];
548 BATut
= env
->DBAT
[0];
551 base
= virtual & 0xFFFC0000;
552 for (i
= 0; i
< env
->nb_BATs
; i
++) {
555 BEPIu
= *BATu
& 0xF0000000;
556 BEPIl
= *BATu
& 0x0FFE0000;
557 if (unlikely(env
->mmu_model
== POWERPC_MMU_601
)) {
558 bat_601_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
560 bat_size_prot(env
, &bl
, &valid
, &prot
, BATu
, BATl
);
562 #if defined (DEBUG_BATS)
564 fprintf(logfile
, "%s: %cBAT%d v " ADDRX
" BATu " ADDRX
565 " BATl " ADDRX
"\n", __func__
,
566 type
== ACCESS_CODE
? 'I' : 'D', i
, virtual, *BATu
, *BATl
);
569 if ((virtual & 0xF0000000) == BEPIu
&&
570 ((virtual & 0x0FFE0000) & ~bl
) == BEPIl
) {
573 /* Get physical address */
574 ctx
->raddr
= (*BATl
& 0xF0000000) |
575 ((virtual & 0x0FFE0000 & bl
) | (*BATl
& 0x0FFE0000)) |
576 (virtual & 0x0001F000);
577 /* Compute access rights */
579 ret
= check_prot(ctx
->prot
, rw
, type
);
580 #if defined (DEBUG_BATS)
581 if (ret
== 0 && loglevel
!= 0) {
582 fprintf(logfile
, "BAT %d match: r " PADDRX
" prot=%c%c\n",
583 i
, ctx
->raddr
, ctx
->prot
& PAGE_READ
? 'R' : '-',
584 ctx
->prot
& PAGE_WRITE
? 'W' : '-');
592 #if defined (DEBUG_BATS)
594 fprintf(logfile
, "no BAT match for " ADDRX
":\n", virtual);
595 for (i
= 0; i
< 4; i
++) {
598 BEPIu
= *BATu
& 0xF0000000;
599 BEPIl
= *BATu
& 0x0FFE0000;
600 bl
= (*BATu
& 0x00001FFC) << 15;
601 fprintf(logfile
, "%s: %cBAT%d v " ADDRX
" BATu " ADDRX
602 " BATl " ADDRX
" \n\t" ADDRX
" " ADDRX
" " ADDRX
"\n",
603 __func__
, type
== ACCESS_CODE
? 'I' : 'D', i
, virtual,
604 *BATu
, *BATl
, BEPIu
, BEPIl
, bl
);
614 /* PTE table lookup */
615 static always_inline
int _find_pte (mmu_ctx_t
*ctx
, int is_64b
, int h
,
618 target_ulong base
, pte0
, pte1
;
622 ret
= -1; /* No entry found */
623 base
= ctx
->pg_addr
[h
];
624 for (i
= 0; i
< 8; i
++) {
625 #if defined(TARGET_PPC64)
627 pte0
= ldq_phys(base
+ (i
* 16));
628 pte1
= ldq_phys(base
+ (i
* 16) + 8);
629 r
= pte64_check(ctx
, pte0
, pte1
, h
, rw
, type
);
630 #if defined (DEBUG_MMU)
632 fprintf(logfile
, "Load pte from " ADDRX
" => " ADDRX
" " ADDRX
633 " %d %d %d " ADDRX
"\n",
634 base
+ (i
* 16), pte0
, pte1
,
635 (int)(pte0
& 1), h
, (int)((pte0
>> 1) & 1),
642 pte0
= ldl_phys(base
+ (i
* 8));
643 pte1
= ldl_phys(base
+ (i
* 8) + 4);
644 r
= pte32_check(ctx
, pte0
, pte1
, h
, rw
, type
);
645 #if defined (DEBUG_MMU)
647 fprintf(logfile
, "Load pte from " ADDRX
" => " ADDRX
" " ADDRX
648 " %d %d %d " ADDRX
"\n",
649 base
+ (i
* 8), pte0
, pte1
,
650 (int)(pte0
>> 31), h
, (int)((pte0
>> 6) & 1),
657 /* PTE inconsistency */
660 /* Access violation */
670 /* XXX: we should go on looping to check all PTEs consistency
671 * but if we can speed-up the whole thing as the
672 * result would be undefined if PTEs are not consistent.
681 #if defined (DEBUG_MMU)
683 fprintf(logfile
, "found PTE at addr " PADDRX
" prot=%01x ret=%d\n",
684 ctx
->raddr
, ctx
->prot
, ret
);
687 /* Update page flags */
689 if (pte_update_flags(ctx
, &pte1
, ret
, rw
) == 1) {
690 #if defined(TARGET_PPC64)
692 stq_phys_notdirty(base
+ (good
* 16) + 8, pte1
);
696 stl_phys_notdirty(base
+ (good
* 8) + 4, pte1
);
704 static always_inline
int find_pte32 (mmu_ctx_t
*ctx
, int h
, int rw
, int type
)
706 return _find_pte(ctx
, 0, h
, rw
, type
);
709 #if defined(TARGET_PPC64)
710 static always_inline
int find_pte64 (mmu_ctx_t
*ctx
, int h
, int rw
, int type
)
712 return _find_pte(ctx
, 1, h
, rw
, type
);
716 static always_inline
int find_pte (CPUState
*env
, mmu_ctx_t
*ctx
,
717 int h
, int rw
, int type
)
719 #if defined(TARGET_PPC64)
720 if (env
->mmu_model
& POWERPC_MMU_64
)
721 return find_pte64(ctx
, h
, rw
, type
);
724 return find_pte32(ctx
, h
, rw
, type
);
727 #if defined(TARGET_PPC64)
728 static always_inline
int slb_is_valid (uint64_t slb64
)
730 return slb64
& 0x0000000008000000ULL
? 1 : 0;
733 static always_inline
void slb_invalidate (uint64_t *slb64
)
735 *slb64
&= ~0x0000000008000000ULL
;
738 static always_inline
int slb_lookup (CPUPPCState
*env
, target_ulong eaddr
,
740 target_ulong
*page_mask
, int *attr
)
742 target_phys_addr_t sr_base
;
749 sr_base
= env
->spr
[SPR_ASR
];
750 #if defined(DEBUG_SLB)
752 fprintf(logfile
, "%s: eaddr " ADDRX
" base " PADDRX
"\n",
753 __func__
, eaddr
, sr_base
);
756 mask
= 0x0000000000000000ULL
; /* Avoid gcc warning */
757 for (n
= 0; n
< env
->slb_nr
; n
++) {
758 tmp64
= ldq_phys(sr_base
);
759 tmp
= ldl_phys(sr_base
+ 8);
760 #if defined(DEBUG_SLB)
762 fprintf(logfile
, "%s: seg %d " PADDRX
" %016" PRIx64
" %08"
763 PRIx32
"\n", __func__
, n
, sr_base
, tmp64
, tmp
);
766 if (slb_is_valid(tmp64
)) {
767 /* SLB entry is valid */
768 switch (tmp64
& 0x0000000006000000ULL
) {
769 case 0x0000000000000000ULL
:
771 mask
= 0xFFFFFFFFF0000000ULL
;
773 case 0x0000000002000000ULL
:
775 mask
= 0xFFFF000000000000ULL
;
777 case 0x0000000004000000ULL
:
778 case 0x0000000006000000ULL
:
779 /* Reserved => segment is invalid */
782 if ((eaddr
& mask
) == (tmp64
& mask
)) {
784 *vsid
= ((tmp64
<< 24) | (tmp
>> 8)) & 0x0003FFFFFFFFFFFFULL
;
797 void ppc_slb_invalidate_all (CPUPPCState
*env
)
799 target_phys_addr_t sr_base
;
801 int n
, do_invalidate
;
804 sr_base
= env
->spr
[SPR_ASR
];
805 /* XXX: Warning: slbia never invalidates the first segment */
806 for (n
= 1; n
< env
->slb_nr
; n
++) {
807 tmp64
= ldq_phys(sr_base
);
808 if (slb_is_valid(tmp64
)) {
809 slb_invalidate(&tmp64
);
810 stq_phys(sr_base
, tmp64
);
811 /* XXX: given the fact that segment size is 256 MB or 1TB,
812 * and we still don't have a tlb_flush_mask(env, n, mask)
813 * in Qemu, we just invalidate all TLBs
823 void ppc_slb_invalidate_one (CPUPPCState
*env
, uint64_t T0
)
825 target_phys_addr_t sr_base
;
826 target_ulong vsid
, page_mask
;
831 n
= slb_lookup(env
, T0
, &vsid
, &page_mask
, &attr
);
833 sr_base
= env
->spr
[SPR_ASR
];
835 tmp64
= ldq_phys(sr_base
);
836 if (slb_is_valid(tmp64
)) {
837 slb_invalidate(&tmp64
);
838 stq_phys(sr_base
, tmp64
);
839 /* XXX: given the fact that segment size is 256 MB or 1TB,
840 * and we still don't have a tlb_flush_mask(env, n, mask)
841 * in Qemu, we just invalidate all TLBs
848 target_ulong
ppc_load_slb (CPUPPCState
*env
, int slb_nr
)
850 target_phys_addr_t sr_base
;
855 sr_base
= env
->spr
[SPR_ASR
];
856 sr_base
+= 12 * slb_nr
;
857 tmp64
= ldq_phys(sr_base
);
858 tmp
= ldl_phys(sr_base
+ 8);
859 if (tmp64
& 0x0000000008000000ULL
) {
860 /* SLB entry is valid */
861 /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
862 rt
= tmp
>> 8; /* 65:88 => 40:63 */
863 rt
|= (tmp64
& 0x7) << 24; /* 62:64 => 37:39 */
864 /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
865 rt
|= ((tmp
>> 4) & 0xF) << 27;
869 #if defined(DEBUG_SLB)
871 fprintf(logfile
, "%s: " PADDRX
" %016" PRIx64
" %08" PRIx32
" => %d "
872 ADDRX
"\n", __func__
, sr_base
, tmp64
, tmp
, slb_nr
, rt
);
879 void ppc_store_slb (CPUPPCState
*env
, int slb_nr
, target_ulong rs
)
881 target_phys_addr_t sr_base
;
885 sr_base
= env
->spr
[SPR_ASR
];
886 sr_base
+= 12 * slb_nr
;
887 /* Copy Rs bits 37:63 to SLB 62:88 */
889 tmp64
= (rs
>> 24) & 0x7;
890 /* Copy Rs bits 33:36 to SLB 89:92 */
891 tmp
|= ((rs
>> 27) & 0xF) << 4;
892 /* Set the valid bit */
895 tmp64
|= (uint32_t)slb_nr
<< 28;
896 #if defined(DEBUG_SLB)
898 fprintf(logfile
, "%s: %d " ADDRX
" => " PADDRX
" %016" PRIx64
899 " %08" PRIx32
"\n", __func__
,
900 slb_nr
, rs
, sr_base
, tmp64
, tmp
);
903 /* Write SLB entry to memory */
904 stq_phys(sr_base
, tmp64
);
905 stl_phys(sr_base
+ 8, tmp
);
907 #endif /* defined(TARGET_PPC64) */
909 /* Perform segment based translation */
910 static always_inline target_phys_addr_t
get_pgaddr (target_phys_addr_t sdr1
,
912 target_phys_addr_t hash
,
913 target_phys_addr_t mask
)
915 return (sdr1
& ((target_phys_addr_t
)(-1ULL) << sdr_sh
)) | (hash
& mask
);
918 static always_inline
int get_segment (CPUState
*env
, mmu_ctx_t
*ctx
,
919 target_ulong eaddr
, int rw
, int type
)
921 target_phys_addr_t sdr
, hash
, mask
, sdr_mask
, htab_mask
;
922 target_ulong sr
, vsid
, vsid_mask
, pgidx
, page_mask
;
923 #if defined(TARGET_PPC64)
926 int ds
, vsid_sh
, sdr_sh
, pr
;
930 #if defined(TARGET_PPC64)
931 if (env
->mmu_model
& POWERPC_MMU_64
) {
932 #if defined (DEBUG_MMU)
934 fprintf(logfile
, "Check SLBs\n");
937 ret
= slb_lookup(env
, eaddr
, &vsid
, &page_mask
, &attr
);
940 ctx
->key
= ((attr
& 0x40) && (pr
!= 0)) ||
941 ((attr
& 0x80) && (pr
== 0)) ? 1 : 0;
943 ctx
->nx
= attr
& 0x20 ? 1 : 0;
944 vsid_mask
= 0x00003FFFFFFFFF80ULL
;
949 #endif /* defined(TARGET_PPC64) */
951 sr
= env
->sr
[eaddr
>> 28];
952 page_mask
= 0x0FFFFFFF;
953 ctx
->key
= (((sr
& 0x20000000) && (pr
!= 0)) ||
954 ((sr
& 0x40000000) && (pr
== 0))) ? 1 : 0;
955 ds
= sr
& 0x80000000 ? 1 : 0;
956 ctx
->nx
= sr
& 0x10000000 ? 1 : 0;
957 vsid
= sr
& 0x00FFFFFF;
958 vsid_mask
= 0x01FFFFC0;
962 #if defined (DEBUG_MMU)
964 fprintf(logfile
, "Check segment v=" ADDRX
" %d " ADDRX
965 " nip=" ADDRX
" lr=" ADDRX
" ir=%d dr=%d pr=%d %d t=%d\n",
966 eaddr
, (int)(eaddr
>> 28), sr
, env
->nip
,
967 env
->lr
, (int)msr_ir
, (int)msr_dr
, pr
!= 0 ? 1 : 0,
972 #if defined (DEBUG_MMU)
974 fprintf(logfile
, "pte segment: key=%d ds %d nx %d vsid " ADDRX
"\n",
975 ctx
->key
, ds
, ctx
->nx
, vsid
);
980 /* Check if instruction fetch is allowed, if needed */
981 if (type
!= ACCESS_CODE
|| ctx
->nx
== 0) {
982 /* Page address translation */
983 /* Primary table address */
985 pgidx
= (eaddr
& page_mask
) >> TARGET_PAGE_BITS
;
986 #if defined(TARGET_PPC64)
987 if (env
->mmu_model
& POWERPC_MMU_64
) {
988 htab_mask
= 0x0FFFFFFF >> (28 - (sdr
& 0x1F));
989 /* XXX: this is false for 1 TB segments */
990 hash
= ((vsid
^ pgidx
) << vsid_sh
) & vsid_mask
;
994 htab_mask
= sdr
& 0x000001FF;
995 hash
= ((vsid
^ pgidx
) << vsid_sh
) & vsid_mask
;
997 mask
= (htab_mask
<< sdr_sh
) | sdr_mask
;
998 #if defined (DEBUG_MMU)
1000 fprintf(logfile
, "sdr " PADDRX
" sh %d hash " PADDRX
1001 " mask " PADDRX
" " ADDRX
"\n",
1002 sdr
, sdr_sh
, hash
, mask
, page_mask
);
1005 ctx
->pg_addr
[0] = get_pgaddr(sdr
, sdr_sh
, hash
, mask
);
1006 /* Secondary table address */
1007 hash
= (~hash
) & vsid_mask
;
1008 #if defined (DEBUG_MMU)
1009 if (loglevel
!= 0) {
1010 fprintf(logfile
, "sdr " PADDRX
" sh %d hash " PADDRX
1011 " mask " PADDRX
"\n",
1012 sdr
, sdr_sh
, hash
, mask
);
1015 ctx
->pg_addr
[1] = get_pgaddr(sdr
, sdr_sh
, hash
, mask
);
1016 #if defined(TARGET_PPC64)
1017 if (env
->mmu_model
& POWERPC_MMU_64
) {
1018 /* Only 5 bits of the page index are used in the AVPN */
1019 ctx
->ptem
= (vsid
<< 12) | ((pgidx
>> 4) & 0x0F80);
1023 ctx
->ptem
= (vsid
<< 7) | (pgidx
>> 10);
1025 /* Initialize real address with an invalid value */
1026 ctx
->raddr
= (target_phys_addr_t
)-1ULL;
1027 if (unlikely(env
->mmu_model
== POWERPC_MMU_SOFT_6xx
||
1028 env
->mmu_model
== POWERPC_MMU_SOFT_74xx
)) {
1029 /* Software TLB search */
1030 ret
= ppc6xx_tlb_check(env
, ctx
, eaddr
, rw
, type
);
1032 #if defined (DEBUG_MMU)
1033 if (loglevel
!= 0) {
1034 fprintf(logfile
, "0 sdr1=" PADDRX
" vsid=" ADDRX
" "
1035 "api=" ADDRX
" hash=" PADDRX
1036 " pg_addr=" PADDRX
"\n",
1037 sdr
, vsid
, pgidx
, hash
, ctx
->pg_addr
[0]);
1040 /* Primary table lookup */
1041 ret
= find_pte(env
, ctx
, 0, rw
, type
);
1043 /* Secondary table lookup */
1044 #if defined (DEBUG_MMU)
1045 if (eaddr
!= 0xEFFFFFFF && loglevel
!= 0) {
1046 fprintf(logfile
, "1 sdr1=" PADDRX
" vsid=" ADDRX
" "
1047 "api=" ADDRX
" hash=" PADDRX
1048 " pg_addr=" PADDRX
"\n",
1049 sdr
, vsid
, pgidx
, hash
, ctx
->pg_addr
[1]);
1052 ret2
= find_pte(env
, ctx
, 1, rw
, type
);
1057 #if defined (DUMP_PAGE_TABLES)
1058 if (loglevel
!= 0) {
1059 target_phys_addr_t curaddr
;
1060 uint32_t a0
, a1
, a2
, a3
;
1061 fprintf(logfile
, "Page table: " PADDRX
" len " PADDRX
"\n",
1063 for (curaddr
= sdr
; curaddr
< (sdr
+ mask
+ 0x80);
1065 a0
= ldl_phys(curaddr
);
1066 a1
= ldl_phys(curaddr
+ 4);
1067 a2
= ldl_phys(curaddr
+ 8);
1068 a3
= ldl_phys(curaddr
+ 12);
1069 if (a0
!= 0 || a1
!= 0 || a2
!= 0 || a3
!= 0) {
1070 fprintf(logfile
, PADDRX
": %08x %08x %08x %08x\n",
1071 curaddr
, a0
, a1
, a2
, a3
);
1077 #if defined (DEBUG_MMU)
1079 fprintf(logfile
, "No access allowed\n");
1084 #if defined (DEBUG_MMU)
1086 fprintf(logfile
, "direct store...\n");
1088 /* Direct-store segment : absolutely *BUGGY* for now */
1091 /* Integer load/store : only access allowed */
1094 /* No code fetch is allowed in direct-store areas */
1097 /* Floating point load/store */
1100 /* lwarx, ldarx or srwcx. */
1103 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
1104 /* Should make the instruction do no-op.
1105 * As it already do no-op, it's quite easy :-)
1110 /* eciwx or ecowx */
1114 fprintf(logfile
, "ERROR: instruction should not need "
1115 "address translation\n");
1119 if ((rw
== 1 || ctx
->key
!= 1) && (rw
== 0 || ctx
->key
!= 0)) {
1130 /* Generic TLB check function for embedded PowerPC implementations */
1131 static always_inline
int ppcemb_tlb_check (CPUState
*env
, ppcemb_tlb_t
*tlb
,
1132 target_phys_addr_t
*raddrp
,
1133 target_ulong address
,
1134 uint32_t pid
, int ext
, int i
)
1138 /* Check valid flag */
1139 if (!(tlb
->prot
& PAGE_VALID
)) {
1141 fprintf(logfile
, "%s: TLB %d not valid\n", __func__
, i
);
1144 mask
= ~(tlb
->size
- 1);
1145 #if defined (DEBUG_SOFTWARE_TLB)
1146 if (loglevel
!= 0) {
1147 fprintf(logfile
, "%s: TLB %d address " ADDRX
" PID %u <=> " ADDRX
1149 __func__
, i
, address
, pid
, tlb
->EPN
, mask
, (uint32_t)tlb
->PID
);
1153 if (tlb
->PID
!= 0 && tlb
->PID
!= pid
)
1155 /* Check effective address */
1156 if ((address
& mask
) != tlb
->EPN
)
1158 *raddrp
= (tlb
->RPN
& mask
) | (address
& ~mask
);
1159 #if (TARGET_PHYS_ADDR_BITS >= 36)
1161 /* Extend the physical address to 36 bits */
1162 *raddrp
|= (target_phys_addr_t
)(tlb
->RPN
& 0xF) << 32;
1169 /* Generic TLB search function for PowerPC embedded implementations */
1170 int ppcemb_tlb_search (CPUPPCState
*env
, target_ulong address
, uint32_t pid
)
1173 target_phys_addr_t raddr
;
1176 /* Default return value is no match */
1178 for (i
= 0; i
< env
->nb_tlb
; i
++) {
1179 tlb
= &env
->tlb
[i
].tlbe
;
1180 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
, pid
, 0, i
) == 0) {
1189 /* Helpers specific to PowerPC 40x implementations */
1190 static always_inline
void ppc4xx_tlb_invalidate_all (CPUState
*env
)
1195 for (i
= 0; i
< env
->nb_tlb
; i
++) {
1196 tlb
= &env
->tlb
[i
].tlbe
;
1197 tlb
->prot
&= ~PAGE_VALID
;
1202 static always_inline
void ppc4xx_tlb_invalidate_virt (CPUState
*env
,
1206 #if !defined(FLUSH_ALL_TLBS)
1208 target_phys_addr_t raddr
;
1209 target_ulong page
, end
;
1212 for (i
= 0; i
< env
->nb_tlb
; i
++) {
1213 tlb
= &env
->tlb
[i
].tlbe
;
1214 if (ppcemb_tlb_check(env
, tlb
, &raddr
, eaddr
, pid
, 0, i
) == 0) {
1215 end
= tlb
->EPN
+ tlb
->size
;
1216 for (page
= tlb
->EPN
; page
< end
; page
+= TARGET_PAGE_SIZE
)
1217 tlb_flush_page(env
, page
);
1218 tlb
->prot
&= ~PAGE_VALID
;
1223 ppc4xx_tlb_invalidate_all(env
);
1227 int mmu40x_get_physical_address (CPUState
*env
, mmu_ctx_t
*ctx
,
1228 target_ulong address
, int rw
, int access_type
)
1231 target_phys_addr_t raddr
;
1232 int i
, ret
, zsel
, zpr
, pr
;
1235 raddr
= (target_phys_addr_t
)-1ULL;
1237 for (i
= 0; i
< env
->nb_tlb
; i
++) {
1238 tlb
= &env
->tlb
[i
].tlbe
;
1239 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
1240 env
->spr
[SPR_40x_PID
], 0, i
) < 0)
1242 zsel
= (tlb
->attr
>> 4) & 0xF;
1243 zpr
= (env
->spr
[SPR_40x_ZPR
] >> (28 - (2 * zsel
))) & 0x3;
1244 #if defined (DEBUG_SOFTWARE_TLB)
1245 if (loglevel
!= 0) {
1246 fprintf(logfile
, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1247 __func__
, i
, zsel
, zpr
, rw
, tlb
->attr
);
1250 /* Check execute enable bit */
1257 /* All accesses granted */
1258 ctx
->prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
1270 /* Check from TLB entry */
1271 /* XXX: there is a problem here or in the TLB fill code... */
1272 ctx
->prot
= tlb
->prot
;
1273 ctx
->prot
|= PAGE_EXEC
;
1274 ret
= check_prot(ctx
->prot
, rw
, access_type
);
1279 #if defined (DEBUG_SOFTWARE_TLB)
1280 if (loglevel
!= 0) {
1281 fprintf(logfile
, "%s: access granted " ADDRX
" => " PADDRX
1282 " %d %d\n", __func__
, address
, ctx
->raddr
, ctx
->prot
,
1289 #if defined (DEBUG_SOFTWARE_TLB)
1290 if (loglevel
!= 0) {
1291 fprintf(logfile
, "%s: access refused " ADDRX
" => " PADDRX
1292 " %d %d\n", __func__
, address
, raddr
, ctx
->prot
,
1300 void store_40x_sler (CPUPPCState
*env
, uint32_t val
)
1302 /* XXX: TO BE FIXED */
1303 if (val
!= 0x00000000) {
1304 cpu_abort(env
, "Little-endian regions are not supported by now\n");
1306 env
->spr
[SPR_405_SLER
] = val
;
1309 int mmubooke_get_physical_address (CPUState
*env
, mmu_ctx_t
*ctx
,
1310 target_ulong address
, int rw
,
1314 target_phys_addr_t raddr
;
1318 raddr
= (target_phys_addr_t
)-1ULL;
1319 for (i
= 0; i
< env
->nb_tlb
; i
++) {
1320 tlb
= &env
->tlb
[i
].tlbe
;
1321 if (ppcemb_tlb_check(env
, tlb
, &raddr
, address
,
1322 env
->spr
[SPR_BOOKE_PID
], 1, i
) < 0)
1325 prot
= tlb
->prot
& 0xF;
1327 prot
= (tlb
->prot
>> 4) & 0xF;
1328 /* Check the address space */
1329 if (access_type
== ACCESS_CODE
) {
1330 if (msr_ir
!= (tlb
->attr
& 1))
1333 if (prot
& PAGE_EXEC
) {
1339 if (msr_dr
!= (tlb
->attr
& 1))
1342 if ((!rw
&& prot
& PAGE_READ
) || (rw
&& (prot
& PAGE_WRITE
))) {
1355 static always_inline
int check_physical (CPUState
*env
, mmu_ctx_t
*ctx
,
1356 target_ulong eaddr
, int rw
)
1361 ctx
->prot
= PAGE_READ
| PAGE_EXEC
;
1363 switch (env
->mmu_model
) {
1364 case POWERPC_MMU_32B
:
1365 case POWERPC_MMU_601
:
1366 case POWERPC_MMU_SOFT_6xx
:
1367 case POWERPC_MMU_SOFT_74xx
:
1368 case POWERPC_MMU_SOFT_4xx
:
1369 case POWERPC_MMU_REAL
:
1370 case POWERPC_MMU_BOOKE
:
1371 ctx
->prot
|= PAGE_WRITE
;
1373 #if defined(TARGET_PPC64)
1374 case POWERPC_MMU_620
:
1375 case POWERPC_MMU_64B
:
1376 /* Real address are 60 bits long */
1377 ctx
->raddr
&= 0x0FFFFFFFFFFFFFFFULL
;
1378 ctx
->prot
|= PAGE_WRITE
;
1381 case POWERPC_MMU_SOFT_4xx_Z
:
1382 if (unlikely(msr_pe
!= 0)) {
1383 /* 403 family add some particular protections,
1384 * using PBL/PBU registers for accesses with no translation.
1387 /* Check PLB validity */
1388 (env
->pb
[0] < env
->pb
[1] &&
1389 /* and address in plb area */
1390 eaddr
>= env
->pb
[0] && eaddr
< env
->pb
[1]) ||
1391 (env
->pb
[2] < env
->pb
[3] &&
1392 eaddr
>= env
->pb
[2] && eaddr
< env
->pb
[3]) ? 1 : 0;
1393 if (in_plb
^ msr_px
) {
1394 /* Access in protected area */
1396 /* Access is not allowed */
1400 /* Read-write access is allowed */
1401 ctx
->prot
|= PAGE_WRITE
;
1405 case POWERPC_MMU_MPC8xx
:
1407 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1409 case POWERPC_MMU_BOOKE_FSL
:
1411 cpu_abort(env
, "BookE FSL MMU model not implemented\n");
1414 cpu_abort(env
, "Unknown or invalid MMU model\n");
1421 int get_physical_address (CPUState
*env
, mmu_ctx_t
*ctx
, target_ulong eaddr
,
1422 int rw
, int access_type
)
1427 if (loglevel
!= 0) {
1428 fprintf(logfile
, "%s\n", __func__
);
1431 if ((access_type
== ACCESS_CODE
&& msr_ir
== 0) ||
1432 (access_type
!= ACCESS_CODE
&& msr_dr
== 0)) {
1433 /* No address translation */
1434 ret
= check_physical(env
, ctx
, eaddr
, rw
);
1437 switch (env
->mmu_model
) {
1438 case POWERPC_MMU_32B
:
1439 case POWERPC_MMU_601
:
1440 case POWERPC_MMU_SOFT_6xx
:
1441 case POWERPC_MMU_SOFT_74xx
:
1442 #if defined(TARGET_PPC64)
1443 case POWERPC_MMU_620
:
1444 case POWERPC_MMU_64B
:
1446 /* Try to find a BAT */
1447 if (env
->nb_BATs
!= 0)
1448 ret
= get_bat(env
, ctx
, eaddr
, rw
, access_type
);
1450 /* We didn't match any BAT entry or don't have BATs */
1451 ret
= get_segment(env
, ctx
, eaddr
, rw
, access_type
);
1454 case POWERPC_MMU_SOFT_4xx
:
1455 case POWERPC_MMU_SOFT_4xx_Z
:
1456 ret
= mmu40x_get_physical_address(env
, ctx
, eaddr
,
1459 case POWERPC_MMU_BOOKE
:
1460 ret
= mmubooke_get_physical_address(env
, ctx
, eaddr
,
1463 case POWERPC_MMU_MPC8xx
:
1465 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1467 case POWERPC_MMU_BOOKE_FSL
:
1469 cpu_abort(env
, "BookE FSL MMU model not implemented\n");
1471 case POWERPC_MMU_REAL
:
1472 cpu_abort(env
, "PowerPC in real mode do not do any translation\n");
1475 cpu_abort(env
, "Unknown or invalid MMU model\n");
1480 if (loglevel
!= 0) {
1481 fprintf(logfile
, "%s address " ADDRX
" => %d " PADDRX
"\n",
1482 __func__
, eaddr
, ret
, ctx
->raddr
);
1489 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
1493 if (unlikely(get_physical_address(env
, &ctx
, addr
, 0, ACCESS_INT
) != 0))
1496 return ctx
.raddr
& TARGET_PAGE_MASK
;
1499 /* Perform address translation */
1500 int cpu_ppc_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
1501 int mmu_idx
, int is_softmmu
)
1510 access_type
= ACCESS_CODE
;
1513 /* XXX: put correct access by using cpu_restore_state()
1515 access_type
= ACCESS_INT
;
1516 // access_type = env->access_type;
1518 ret
= get_physical_address(env
, &ctx
, address
, rw
, access_type
);
1520 ret
= tlb_set_page_exec(env
, address
& TARGET_PAGE_MASK
,
1521 ctx
.raddr
& TARGET_PAGE_MASK
, ctx
.prot
,
1522 mmu_idx
, is_softmmu
);
1523 } else if (ret
< 0) {
1524 #if defined (DEBUG_MMU)
1526 cpu_dump_state(env
, logfile
, fprintf
, 0);
1528 if (access_type
== ACCESS_CODE
) {
1531 /* No matches in page tables or TLB */
1532 switch (env
->mmu_model
) {
1533 case POWERPC_MMU_SOFT_6xx
:
1534 env
->exception_index
= POWERPC_EXCP_IFTLB
;
1535 env
->error_code
= 1 << 18;
1536 env
->spr
[SPR_IMISS
] = address
;
1537 env
->spr
[SPR_ICMP
] = 0x80000000 | ctx
.ptem
;
1539 case POWERPC_MMU_SOFT_74xx
:
1540 env
->exception_index
= POWERPC_EXCP_IFTLB
;
1542 case POWERPC_MMU_SOFT_4xx
:
1543 case POWERPC_MMU_SOFT_4xx_Z
:
1544 env
->exception_index
= POWERPC_EXCP_ITLB
;
1545 env
->error_code
= 0;
1546 env
->spr
[SPR_40x_DEAR
] = address
;
1547 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1549 case POWERPC_MMU_32B
:
1550 case POWERPC_MMU_601
:
1551 #if defined(TARGET_PPC64)
1552 case POWERPC_MMU_620
:
1553 case POWERPC_MMU_64B
:
1555 env
->exception_index
= POWERPC_EXCP_ISI
;
1556 env
->error_code
= 0x40000000;
1558 case POWERPC_MMU_BOOKE
:
1560 cpu_abort(env
, "BookE MMU model is not implemented\n");
1562 case POWERPC_MMU_BOOKE_FSL
:
1564 cpu_abort(env
, "BookE FSL MMU model is not implemented\n");
1566 case POWERPC_MMU_MPC8xx
:
1568 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1570 case POWERPC_MMU_REAL
:
1571 cpu_abort(env
, "PowerPC in real mode should never raise "
1572 "any MMU exceptions\n");
1575 cpu_abort(env
, "Unknown or invalid MMU model\n");
1580 /* Access rights violation */
1581 env
->exception_index
= POWERPC_EXCP_ISI
;
1582 env
->error_code
= 0x08000000;
1585 /* No execute protection violation */
1586 env
->exception_index
= POWERPC_EXCP_ISI
;
1587 env
->error_code
= 0x10000000;
1590 /* Direct store exception */
1591 /* No code fetch is allowed in direct-store areas */
1592 env
->exception_index
= POWERPC_EXCP_ISI
;
1593 env
->error_code
= 0x10000000;
1595 #if defined(TARGET_PPC64)
1597 /* No match in segment table */
1598 if (env
->mmu_model
== POWERPC_MMU_620
) {
1599 env
->exception_index
= POWERPC_EXCP_ISI
;
1600 /* XXX: this might be incorrect */
1601 env
->error_code
= 0x40000000;
1603 env
->exception_index
= POWERPC_EXCP_ISEG
;
1604 env
->error_code
= 0;
1612 /* No matches in page tables or TLB */
1613 switch (env
->mmu_model
) {
1614 case POWERPC_MMU_SOFT_6xx
:
1616 env
->exception_index
= POWERPC_EXCP_DSTLB
;
1617 env
->error_code
= 1 << 16;
1619 env
->exception_index
= POWERPC_EXCP_DLTLB
;
1620 env
->error_code
= 0;
1622 env
->spr
[SPR_DMISS
] = address
;
1623 env
->spr
[SPR_DCMP
] = 0x80000000 | ctx
.ptem
;
1625 env
->error_code
|= ctx
.key
<< 19;
1626 env
->spr
[SPR_HASH1
] = ctx
.pg_addr
[0];
1627 env
->spr
[SPR_HASH2
] = ctx
.pg_addr
[1];
1629 case POWERPC_MMU_SOFT_74xx
:
1631 env
->exception_index
= POWERPC_EXCP_DSTLB
;
1633 env
->exception_index
= POWERPC_EXCP_DLTLB
;
1636 /* Implement LRU algorithm */
1637 env
->error_code
= ctx
.key
<< 19;
1638 env
->spr
[SPR_TLBMISS
] = (address
& ~((target_ulong
)0x3)) |
1639 ((env
->last_way
+ 1) & (env
->nb_ways
- 1));
1640 env
->spr
[SPR_PTEHI
] = 0x80000000 | ctx
.ptem
;
1642 case POWERPC_MMU_SOFT_4xx
:
1643 case POWERPC_MMU_SOFT_4xx_Z
:
1644 env
->exception_index
= POWERPC_EXCP_DTLB
;
1645 env
->error_code
= 0;
1646 env
->spr
[SPR_40x_DEAR
] = address
;
1648 env
->spr
[SPR_40x_ESR
] = 0x00800000;
1650 env
->spr
[SPR_40x_ESR
] = 0x00000000;
1652 case POWERPC_MMU_32B
:
1653 case POWERPC_MMU_601
:
1654 #if defined(TARGET_PPC64)
1655 case POWERPC_MMU_620
:
1656 case POWERPC_MMU_64B
:
1658 env
->exception_index
= POWERPC_EXCP_DSI
;
1659 env
->error_code
= 0;
1660 env
->spr
[SPR_DAR
] = address
;
1662 env
->spr
[SPR_DSISR
] = 0x42000000;
1664 env
->spr
[SPR_DSISR
] = 0x40000000;
1666 case POWERPC_MMU_MPC8xx
:
1668 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1670 case POWERPC_MMU_BOOKE
:
1672 cpu_abort(env
, "BookE MMU model is not implemented\n");
1674 case POWERPC_MMU_BOOKE_FSL
:
1676 cpu_abort(env
, "BookE FSL MMU model is not implemented\n");
1678 case POWERPC_MMU_REAL
:
1679 cpu_abort(env
, "PowerPC in real mode should never raise "
1680 "any MMU exceptions\n");
1683 cpu_abort(env
, "Unknown or invalid MMU model\n");
1688 /* Access rights violation */
1689 env
->exception_index
= POWERPC_EXCP_DSI
;
1690 env
->error_code
= 0;
1691 env
->spr
[SPR_DAR
] = address
;
1693 env
->spr
[SPR_DSISR
] = 0x0A000000;
1695 env
->spr
[SPR_DSISR
] = 0x08000000;
1698 /* Direct store exception */
1699 switch (access_type
) {
1701 /* Floating point load/store */
1702 env
->exception_index
= POWERPC_EXCP_ALIGN
;
1703 env
->error_code
= POWERPC_EXCP_ALIGN_FP
;
1704 env
->spr
[SPR_DAR
] = address
;
1707 /* lwarx, ldarx or stwcx. */
1708 env
->exception_index
= POWERPC_EXCP_DSI
;
1709 env
->error_code
= 0;
1710 env
->spr
[SPR_DAR
] = address
;
1712 env
->spr
[SPR_DSISR
] = 0x06000000;
1714 env
->spr
[SPR_DSISR
] = 0x04000000;
1717 /* eciwx or ecowx */
1718 env
->exception_index
= POWERPC_EXCP_DSI
;
1719 env
->error_code
= 0;
1720 env
->spr
[SPR_DAR
] = address
;
1722 env
->spr
[SPR_DSISR
] = 0x06100000;
1724 env
->spr
[SPR_DSISR
] = 0x04100000;
1727 printf("DSI: invalid exception (%d)\n", ret
);
1728 env
->exception_index
= POWERPC_EXCP_PROGRAM
;
1730 POWERPC_EXCP_INVAL
| POWERPC_EXCP_INVAL_INVAL
;
1731 env
->spr
[SPR_DAR
] = address
;
1735 #if defined(TARGET_PPC64)
1737 /* No match in segment table */
1738 if (env
->mmu_model
== POWERPC_MMU_620
) {
1739 env
->exception_index
= POWERPC_EXCP_DSI
;
1740 env
->error_code
= 0;
1741 env
->spr
[SPR_DAR
] = address
;
1742 /* XXX: this might be incorrect */
1744 env
->spr
[SPR_DSISR
] = 0x42000000;
1746 env
->spr
[SPR_DSISR
] = 0x40000000;
1748 env
->exception_index
= POWERPC_EXCP_DSEG
;
1749 env
->error_code
= 0;
1750 env
->spr
[SPR_DAR
] = address
;
1757 printf("%s: set exception to %d %02x\n", __func__
,
1758 env
->exception
, env
->error_code
);
1766 /*****************************************************************************/
1767 /* BATs management */
1768 #if !defined(FLUSH_ALL_TLBS)
1769 static always_inline
void do_invalidate_BAT (CPUPPCState
*env
,
1773 target_ulong base
, end
, page
;
1775 base
= BATu
& ~0x0001FFFF;
1776 end
= base
+ mask
+ 0x00020000;
1777 #if defined (DEBUG_BATS)
1778 if (loglevel
!= 0) {
1779 fprintf(logfile
, "Flush BAT from " ADDRX
" to " ADDRX
" (" ADDRX
")\n",
1783 for (page
= base
; page
!= end
; page
+= TARGET_PAGE_SIZE
)
1784 tlb_flush_page(env
, page
);
1785 #if defined (DEBUG_BATS)
1787 fprintf(logfile
, "Flush done\n");
1792 static always_inline
void dump_store_bat (CPUPPCState
*env
, char ID
,
1793 int ul
, int nr
, target_ulong value
)
1795 #if defined (DEBUG_BATS)
1796 if (loglevel
!= 0) {
1797 fprintf(logfile
, "Set %cBAT%d%c to " ADDRX
" (" ADDRX
")\n",
1798 ID
, nr
, ul
== 0 ? 'u' : 'l', value
, env
->nip
);
1803 target_ulong
do_load_ibatu (CPUPPCState
*env
, int nr
)
1805 return env
->IBAT
[0][nr
];
1808 target_ulong
do_load_ibatl (CPUPPCState
*env
, int nr
)
1810 return env
->IBAT
[1][nr
];
1813 void do_store_ibatu (CPUPPCState
*env
, int nr
, target_ulong value
)
1817 dump_store_bat(env
, 'I', 0, nr
, value
);
1818 if (env
->IBAT
[0][nr
] != value
) {
1819 mask
= (value
<< 15) & 0x0FFE0000UL
;
1820 #if !defined(FLUSH_ALL_TLBS)
1821 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1823 /* When storing valid upper BAT, mask BEPI and BRPN
1824 * and invalidate all TLBs covered by this BAT
1826 mask
= (value
<< 15) & 0x0FFE0000UL
;
1827 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1828 (value
& ~0x0001FFFFUL
& ~mask
);
1829 env
->IBAT
[1][nr
] = (env
->IBAT
[1][nr
] & 0x0000007B) |
1830 (env
->IBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1831 #if !defined(FLUSH_ALL_TLBS)
1832 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1839 void do_store_ibatl (CPUPPCState
*env
, int nr
, target_ulong value
)
1841 dump_store_bat(env
, 'I', 1, nr
, value
);
1842 env
->IBAT
[1][nr
] = value
;
1845 target_ulong
do_load_dbatu (CPUPPCState
*env
, int nr
)
1847 return env
->DBAT
[0][nr
];
1850 target_ulong
do_load_dbatl (CPUPPCState
*env
, int nr
)
1852 return env
->DBAT
[1][nr
];
1855 void do_store_dbatu (CPUPPCState
*env
, int nr
, target_ulong value
)
1859 dump_store_bat(env
, 'D', 0, nr
, value
);
1860 if (env
->DBAT
[0][nr
] != value
) {
1861 /* When storing valid upper BAT, mask BEPI and BRPN
1862 * and invalidate all TLBs covered by this BAT
1864 mask
= (value
<< 15) & 0x0FFE0000UL
;
1865 #if !defined(FLUSH_ALL_TLBS)
1866 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1868 mask
= (value
<< 15) & 0x0FFE0000UL
;
1869 env
->DBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1870 (value
& ~0x0001FFFFUL
& ~mask
);
1871 env
->DBAT
[1][nr
] = (env
->DBAT
[1][nr
] & 0x0000007B) |
1872 (env
->DBAT
[1][nr
] & ~0x0001FFFF & ~mask
);
1873 #if !defined(FLUSH_ALL_TLBS)
1874 do_invalidate_BAT(env
, env
->DBAT
[0][nr
], mask
);
1881 void do_store_dbatl (CPUPPCState
*env
, int nr
, target_ulong value
)
1883 dump_store_bat(env
, 'D', 1, nr
, value
);
1884 env
->DBAT
[1][nr
] = value
;
1887 void do_store_ibatu_601 (CPUPPCState
*env
, int nr
, target_ulong value
)
1892 dump_store_bat(env
, 'I', 0, nr
, value
);
1893 if (env
->IBAT
[0][nr
] != value
) {
1895 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1896 if (env
->IBAT
[1][nr
] & 0x40) {
1897 /* Invalidate BAT only if it is valid */
1898 #if !defined(FLUSH_ALL_TLBS)
1899 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1904 /* When storing valid upper BAT, mask BEPI and BRPN
1905 * and invalidate all TLBs covered by this BAT
1907 env
->IBAT
[0][nr
] = (value
& 0x00001FFFUL
) |
1908 (value
& ~0x0001FFFFUL
& ~mask
);
1909 env
->DBAT
[0][nr
] = env
->IBAT
[0][nr
];
1910 if (env
->IBAT
[1][nr
] & 0x40) {
1911 #if !defined(FLUSH_ALL_TLBS)
1912 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1917 #if defined(FLUSH_ALL_TLBS)
1924 void do_store_ibatl_601 (CPUPPCState
*env
, int nr
, target_ulong value
)
1929 dump_store_bat(env
, 'I', 1, nr
, value
);
1930 if (env
->IBAT
[1][nr
] != value
) {
1932 if (env
->IBAT
[1][nr
] & 0x40) {
1933 #if !defined(FLUSH_ALL_TLBS)
1934 mask
= (env
->IBAT
[1][nr
] << 17) & 0x0FFE0000UL
;
1935 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1941 #if !defined(FLUSH_ALL_TLBS)
1942 mask
= (value
<< 17) & 0x0FFE0000UL
;
1943 do_invalidate_BAT(env
, env
->IBAT
[0][nr
], mask
);
1948 env
->IBAT
[1][nr
] = value
;
1949 env
->DBAT
[1][nr
] = value
;
1950 #if defined(FLUSH_ALL_TLBS)
1957 /*****************************************************************************/
1958 /* TLB management */
1959 void ppc_tlb_invalidate_all (CPUPPCState
*env
)
1961 switch (env
->mmu_model
) {
1962 case POWERPC_MMU_SOFT_6xx
:
1963 case POWERPC_MMU_SOFT_74xx
:
1964 ppc6xx_tlb_invalidate_all(env
);
1966 case POWERPC_MMU_SOFT_4xx
:
1967 case POWERPC_MMU_SOFT_4xx_Z
:
1968 ppc4xx_tlb_invalidate_all(env
);
1970 case POWERPC_MMU_REAL
:
1971 cpu_abort(env
, "No TLB for PowerPC 4xx in real mode\n");
1973 case POWERPC_MMU_MPC8xx
:
1975 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
1977 case POWERPC_MMU_BOOKE
:
1979 cpu_abort(env
, "BookE MMU model is not implemented\n");
1981 case POWERPC_MMU_BOOKE_FSL
:
1983 cpu_abort(env
, "BookE MMU model is not implemented\n");
1985 case POWERPC_MMU_32B
:
1986 case POWERPC_MMU_601
:
1987 #if defined(TARGET_PPC64)
1988 case POWERPC_MMU_620
:
1989 case POWERPC_MMU_64B
:
1990 #endif /* defined(TARGET_PPC64) */
1995 cpu_abort(env
, "Unknown MMU model\n");
2000 void ppc_tlb_invalidate_one (CPUPPCState
*env
, target_ulong addr
)
2002 #if !defined(FLUSH_ALL_TLBS)
2003 addr
&= TARGET_PAGE_MASK
;
2004 switch (env
->mmu_model
) {
2005 case POWERPC_MMU_SOFT_6xx
:
2006 case POWERPC_MMU_SOFT_74xx
:
2007 ppc6xx_tlb_invalidate_virt(env
, addr
, 0);
2008 if (env
->id_tlbs
== 1)
2009 ppc6xx_tlb_invalidate_virt(env
, addr
, 1);
2011 case POWERPC_MMU_SOFT_4xx
:
2012 case POWERPC_MMU_SOFT_4xx_Z
:
2013 ppc4xx_tlb_invalidate_virt(env
, addr
, env
->spr
[SPR_40x_PID
]);
2015 case POWERPC_MMU_REAL
:
2016 cpu_abort(env
, "No TLB for PowerPC 4xx in real mode\n");
2018 case POWERPC_MMU_MPC8xx
:
2020 cpu_abort(env
, "MPC8xx MMU model is not implemented\n");
2022 case POWERPC_MMU_BOOKE
:
2024 cpu_abort(env
, "BookE MMU model is not implemented\n");
2026 case POWERPC_MMU_BOOKE_FSL
:
2028 cpu_abort(env
, "BookE FSL MMU model is not implemented\n");
2030 case POWERPC_MMU_32B
:
2031 case POWERPC_MMU_601
:
2032 /* tlbie invalidate TLBs for all segments */
2033 addr
&= ~((target_ulong
)-1ULL << 28);
2034 /* XXX: this case should be optimized,
2035 * giving a mask to tlb_flush_page
2037 tlb_flush_page(env
, addr
| (0x0 << 28));
2038 tlb_flush_page(env
, addr
| (0x1 << 28));
2039 tlb_flush_page(env
, addr
| (0x2 << 28));
2040 tlb_flush_page(env
, addr
| (0x3 << 28));
2041 tlb_flush_page(env
, addr
| (0x4 << 28));
2042 tlb_flush_page(env
, addr
| (0x5 << 28));
2043 tlb_flush_page(env
, addr
| (0x6 << 28));
2044 tlb_flush_page(env
, addr
| (0x7 << 28));
2045 tlb_flush_page(env
, addr
| (0x8 << 28));
2046 tlb_flush_page(env
, addr
| (0x9 << 28));
2047 tlb_flush_page(env
, addr
| (0xA << 28));
2048 tlb_flush_page(env
, addr
| (0xB << 28));
2049 tlb_flush_page(env
, addr
| (0xC << 28));
2050 tlb_flush_page(env
, addr
| (0xD << 28));
2051 tlb_flush_page(env
, addr
| (0xE << 28));
2052 tlb_flush_page(env
, addr
| (0xF << 28));
2054 #if defined(TARGET_PPC64)
2055 case POWERPC_MMU_620
:
2056 case POWERPC_MMU_64B
:
2057 /* tlbie invalidate TLBs for all segments */
2058 /* XXX: given the fact that there are too many segments to invalidate,
2059 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2060 * we just invalidate all TLBs
2064 #endif /* defined(TARGET_PPC64) */
2067 cpu_abort(env
, "Unknown MMU model\n");
2071 ppc_tlb_invalidate_all(env
);
2075 /*****************************************************************************/
2076 /* Special registers manipulation */
2077 #if defined(TARGET_PPC64)
2078 target_ulong
ppc_load_asr (CPUPPCState
*env
)
2083 void ppc_store_asr (CPUPPCState
*env
, target_ulong value
)
2085 if (env
->asr
!= value
) {
2092 target_ulong
do_load_sdr1 (CPUPPCState
*env
)
2097 void do_store_sdr1 (CPUPPCState
*env
, target_ulong value
)
2099 #if defined (DEBUG_MMU)
2100 if (loglevel
!= 0) {
2101 fprintf(logfile
, "%s: " ADDRX
"\n", __func__
, value
);
2104 if (env
->sdr1
!= value
) {
2105 /* XXX: for PowerPC 64, should check that the HTABSIZE value
2114 target_ulong
do_load_sr (CPUPPCState
*env
, int srnum
)
2116 return env
->sr
[srnum
];
2120 void do_store_sr (CPUPPCState
*env
, int srnum
, target_ulong value
)
2122 #if defined (DEBUG_MMU)
2123 if (loglevel
!= 0) {
2124 fprintf(logfile
, "%s: reg=%d " ADDRX
" " ADDRX
"\n",
2125 __func__
, srnum
, value
, env
->sr
[srnum
]);
2128 if (env
->sr
[srnum
] != value
) {
2129 env
->sr
[srnum
] = value
;
2130 #if !defined(FLUSH_ALL_TLBS) && 0
2132 target_ulong page
, end
;
2133 /* Invalidate 256 MB of virtual memory */
2134 page
= (16 << 20) * srnum
;
2135 end
= page
+ (16 << 20);
2136 for (; page
!= end
; page
+= TARGET_PAGE_SIZE
)
2137 tlb_flush_page(env
, page
);
2144 #endif /* !defined (CONFIG_USER_ONLY) */
2146 /* GDBstub can read and write MSR... */
2147 void ppc_store_msr (CPUPPCState
*env
, target_ulong value
)
2149 hreg_store_msr(env
, value
, 0);
2152 /*****************************************************************************/
2153 /* Exception processing */
2154 #if defined (CONFIG_USER_ONLY)
2155 void do_interrupt (CPUState
*env
)
2157 env
->exception_index
= POWERPC_EXCP_NONE
;
2158 env
->error_code
= 0;
2161 void ppc_hw_interrupt (CPUState
*env
)
2163 env
->exception_index
= POWERPC_EXCP_NONE
;
2164 env
->error_code
= 0;
2166 #else /* defined (CONFIG_USER_ONLY) */
2167 static always_inline
void dump_syscall (CPUState
*env
)
2169 fprintf(logfile
, "syscall r0=" REGX
" r3=" REGX
" r4=" REGX
2170 " r5=" REGX
" r6=" REGX
" nip=" ADDRX
"\n",
2171 ppc_dump_gpr(env
, 0), ppc_dump_gpr(env
, 3), ppc_dump_gpr(env
, 4),
2172 ppc_dump_gpr(env
, 5), ppc_dump_gpr(env
, 6), env
->nip
);
2175 /* Note that this function should be greatly optimized
2176 * when called with a constant excp, from ppc_hw_interrupt
2178 static always_inline
void powerpc_excp (CPUState
*env
,
2179 int excp_model
, int excp
)
2181 target_ulong msr
, new_msr
, vector
;
2182 int srr0
, srr1
, asrr0
, asrr1
;
2183 int lpes0
, lpes1
, lev
;
2186 /* XXX: find a suitable condition to enable the hypervisor mode */
2187 lpes0
= (env
->spr
[SPR_LPCR
] >> 1) & 1;
2188 lpes1
= (env
->spr
[SPR_LPCR
] >> 2) & 1;
2190 /* Those values ensure we won't enter the hypervisor mode */
2195 if (loglevel
& CPU_LOG_INT
) {
2196 fprintf(logfile
, "Raise exception at " ADDRX
" => %08x (%02x)\n",
2197 env
->nip
, excp
, env
->error_code
);
2205 msr
&= ~((target_ulong
)0x783F0000);
2207 case POWERPC_EXCP_NONE
:
2208 /* Should never happen */
2210 case POWERPC_EXCP_CRITICAL
: /* Critical input */
2211 new_msr
&= ~((target_ulong
)1 << MSR_RI
); /* XXX: check this */
2212 switch (excp_model
) {
2213 case POWERPC_EXCP_40x
:
2214 srr0
= SPR_40x_SRR2
;
2215 srr1
= SPR_40x_SRR3
;
2217 case POWERPC_EXCP_BOOKE
:
2218 srr0
= SPR_BOOKE_CSRR0
;
2219 srr1
= SPR_BOOKE_CSRR1
;
2221 case POWERPC_EXCP_G2
:
2227 case POWERPC_EXCP_MCHECK
: /* Machine check exception */
2229 /* Machine check exception is not enabled.
2230 * Enter checkstop state.
2232 if (loglevel
!= 0) {
2233 fprintf(logfile
, "Machine check while not allowed. "
2234 "Entering checkstop state\n");
2236 fprintf(stderr
, "Machine check while not allowed. "
2237 "Entering checkstop state\n");
2240 env
->interrupt_request
|= CPU_INTERRUPT_EXITTB
;
2242 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2243 new_msr
&= ~((target_ulong
)1 << MSR_ME
);
2245 /* XXX: find a suitable condition to enable the hypervisor mode */
2246 new_msr
|= (target_ulong
)MSR_HVB
;
2248 /* XXX: should also have something loaded in DAR / DSISR */
2249 switch (excp_model
) {
2250 case POWERPC_EXCP_40x
:
2251 srr0
= SPR_40x_SRR2
;
2252 srr1
= SPR_40x_SRR3
;
2254 case POWERPC_EXCP_BOOKE
:
2255 srr0
= SPR_BOOKE_MCSRR0
;
2256 srr1
= SPR_BOOKE_MCSRR1
;
2257 asrr0
= SPR_BOOKE_CSRR0
;
2258 asrr1
= SPR_BOOKE_CSRR1
;
2264 case POWERPC_EXCP_DSI
: /* Data storage exception */
2265 #if defined (DEBUG_EXCEPTIONS)
2266 if (loglevel
!= 0) {
2267 fprintf(logfile
, "DSI exception: DSISR=" ADDRX
" DAR=" ADDRX
"\n",
2268 env
->spr
[SPR_DSISR
], env
->spr
[SPR_DAR
]);
2271 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2273 new_msr
|= (target_ulong
)MSR_HVB
;
2275 case POWERPC_EXCP_ISI
: /* Instruction storage exception */
2276 #if defined (DEBUG_EXCEPTIONS)
2277 if (loglevel
!= 0) {
2278 fprintf(logfile
, "ISI exception: msr=" ADDRX
", nip=" ADDRX
"\n",
2282 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2284 new_msr
|= (target_ulong
)MSR_HVB
;
2285 msr
|= env
->error_code
;
2287 case POWERPC_EXCP_EXTERNAL
: /* External input */
2288 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2290 new_msr
|= (target_ulong
)MSR_HVB
;
2292 case POWERPC_EXCP_ALIGN
: /* Alignment exception */
2293 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2295 new_msr
|= (target_ulong
)MSR_HVB
;
2296 /* XXX: this is false */
2297 /* Get rS/rD and rA from faulting opcode */
2298 env
->spr
[SPR_DSISR
] |= (ldl_code((env
->nip
- 4)) & 0x03FF0000) >> 16;
2300 case POWERPC_EXCP_PROGRAM
: /* Program exception */
2301 switch (env
->error_code
& ~0xF) {
2302 case POWERPC_EXCP_FP
:
2303 if ((msr_fe0
== 0 && msr_fe1
== 0) || msr_fp
== 0) {
2304 #if defined (DEBUG_EXCEPTIONS)
2305 if (loglevel
!= 0) {
2306 fprintf(logfile
, "Ignore floating point exception\n");
2309 env
->exception_index
= POWERPC_EXCP_NONE
;
2310 env
->error_code
= 0;
2313 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2315 new_msr
|= (target_ulong
)MSR_HVB
;
2317 if (msr_fe0
== msr_fe1
)
2321 case POWERPC_EXCP_INVAL
:
2322 #if defined (DEBUG_EXCEPTIONS)
2323 if (loglevel
!= 0) {
2324 fprintf(logfile
, "Invalid instruction at " ADDRX
"\n",
2328 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2330 new_msr
|= (target_ulong
)MSR_HVB
;
2333 case POWERPC_EXCP_PRIV
:
2334 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2336 new_msr
|= (target_ulong
)MSR_HVB
;
2339 case POWERPC_EXCP_TRAP
:
2340 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2342 new_msr
|= (target_ulong
)MSR_HVB
;
2346 /* Should never occur */
2347 cpu_abort(env
, "Invalid program exception %d. Aborting\n",
2352 case POWERPC_EXCP_FPU
: /* Floating-point unavailable exception */
2353 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2355 new_msr
|= (target_ulong
)MSR_HVB
;
2357 case POWERPC_EXCP_SYSCALL
: /* System call exception */
2358 /* NOTE: this is a temporary hack to support graphics OSI
2359 calls from the MOL driver */
2360 /* XXX: To be removed */
2361 if (env
->gpr
[3] == 0x113724fa && env
->gpr
[4] == 0x77810f9b &&
2363 if (env
->osi_call(env
) != 0) {
2364 env
->exception_index
= POWERPC_EXCP_NONE
;
2365 env
->error_code
= 0;
2369 if (loglevel
& CPU_LOG_INT
) {
2372 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2373 lev
= env
->error_code
;
2374 if (lev
== 1 || (lpes0
== 0 && lpes1
== 0))
2375 new_msr
|= (target_ulong
)MSR_HVB
;
2377 case POWERPC_EXCP_APU
: /* Auxiliary processor unavailable */
2378 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2380 case POWERPC_EXCP_DECR
: /* Decrementer exception */
2381 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2383 new_msr
|= (target_ulong
)MSR_HVB
;
2385 case POWERPC_EXCP_FIT
: /* Fixed-interval timer interrupt */
2387 #if defined (DEBUG_EXCEPTIONS)
2389 fprintf(logfile
, "FIT exception\n");
2391 new_msr
&= ~((target_ulong
)1 << MSR_RI
); /* XXX: check this */
2393 case POWERPC_EXCP_WDT
: /* Watchdog timer interrupt */
2394 #if defined (DEBUG_EXCEPTIONS)
2396 fprintf(logfile
, "WDT exception\n");
2398 switch (excp_model
) {
2399 case POWERPC_EXCP_BOOKE
:
2400 srr0
= SPR_BOOKE_CSRR0
;
2401 srr1
= SPR_BOOKE_CSRR1
;
2406 new_msr
&= ~((target_ulong
)1 << MSR_RI
); /* XXX: check this */
2408 case POWERPC_EXCP_DTLB
: /* Data TLB error */
2409 new_msr
&= ~((target_ulong
)1 << MSR_RI
); /* XXX: check this */
2411 case POWERPC_EXCP_ITLB
: /* Instruction TLB error */
2412 new_msr
&= ~((target_ulong
)1 << MSR_RI
); /* XXX: check this */
2414 case POWERPC_EXCP_DEBUG
: /* Debug interrupt */
2415 switch (excp_model
) {
2416 case POWERPC_EXCP_BOOKE
:
2417 srr0
= SPR_BOOKE_DSRR0
;
2418 srr1
= SPR_BOOKE_DSRR1
;
2419 asrr0
= SPR_BOOKE_CSRR0
;
2420 asrr1
= SPR_BOOKE_CSRR1
;
2426 cpu_abort(env
, "Debug exception is not implemented yet !\n");
2428 case POWERPC_EXCP_SPEU
: /* SPE/embedded floating-point unavailable */
2429 new_msr
&= ~((target_ulong
)1 << MSR_RI
); /* XXX: check this */
2431 case POWERPC_EXCP_EFPDI
: /* Embedded floating-point data interrupt */
2433 cpu_abort(env
, "Embedded floating point data exception "
2434 "is not implemented yet !\n");
2436 case POWERPC_EXCP_EFPRI
: /* Embedded floating-point round interrupt */
2438 cpu_abort(env
, "Embedded floating point round exception "
2439 "is not implemented yet !\n");
2441 case POWERPC_EXCP_EPERFM
: /* Embedded performance monitor interrupt */
2442 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2445 "Performance counter exception is not implemented yet !\n");
2447 case POWERPC_EXCP_DOORI
: /* Embedded doorbell interrupt */
2450 "Embedded doorbell interrupt is not implemented yet !\n");
2452 case POWERPC_EXCP_DOORCI
: /* Embedded doorbell critical interrupt */
2453 switch (excp_model
) {
2454 case POWERPC_EXCP_BOOKE
:
2455 srr0
= SPR_BOOKE_CSRR0
;
2456 srr1
= SPR_BOOKE_CSRR1
;
2462 cpu_abort(env
, "Embedded doorbell critical interrupt "
2463 "is not implemented yet !\n");
2465 case POWERPC_EXCP_RESET
: /* System reset exception */
2466 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2468 /* XXX: find a suitable condition to enable the hypervisor mode */
2469 new_msr
|= (target_ulong
)MSR_HVB
;
2472 case POWERPC_EXCP_DSEG
: /* Data segment exception */
2473 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2475 new_msr
|= (target_ulong
)MSR_HVB
;
2477 case POWERPC_EXCP_ISEG
: /* Instruction segment exception */
2478 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2480 new_msr
|= (target_ulong
)MSR_HVB
;
2482 case POWERPC_EXCP_HDECR
: /* Hypervisor decrementer exception */
2485 new_msr
|= (target_ulong
)MSR_HVB
;
2487 case POWERPC_EXCP_TRACE
: /* Trace exception */
2488 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2490 new_msr
|= (target_ulong
)MSR_HVB
;
2492 case POWERPC_EXCP_HDSI
: /* Hypervisor data storage exception */
2495 new_msr
|= (target_ulong
)MSR_HVB
;
2497 case POWERPC_EXCP_HISI
: /* Hypervisor instruction storage exception */
2500 new_msr
|= (target_ulong
)MSR_HVB
;
2502 case POWERPC_EXCP_HDSEG
: /* Hypervisor data segment exception */
2505 new_msr
|= (target_ulong
)MSR_HVB
;
2507 case POWERPC_EXCP_HISEG
: /* Hypervisor instruction segment exception */
2510 new_msr
|= (target_ulong
)MSR_HVB
;
2512 case POWERPC_EXCP_VPU
: /* Vector unavailable exception */
2513 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2515 new_msr
|= (target_ulong
)MSR_HVB
;
2517 case POWERPC_EXCP_PIT
: /* Programmable interval timer interrupt */
2518 #if defined (DEBUG_EXCEPTIONS)
2520 fprintf(logfile
, "PIT exception\n");
2522 new_msr
&= ~((target_ulong
)1 << MSR_RI
); /* XXX: check this */
2524 case POWERPC_EXCP_IO
: /* IO error exception */
2526 cpu_abort(env
, "601 IO error exception is not implemented yet !\n");
2528 case POWERPC_EXCP_RUNM
: /* Run mode exception */
2530 cpu_abort(env
, "601 run mode exception is not implemented yet !\n");
2532 case POWERPC_EXCP_EMUL
: /* Emulation trap exception */
2534 cpu_abort(env
, "602 emulation trap exception "
2535 "is not implemented yet !\n");
2537 case POWERPC_EXCP_IFTLB
: /* Instruction fetch TLB error */
2538 new_msr
&= ~((target_ulong
)1 << MSR_RI
); /* XXX: check this */
2539 if (lpes1
== 0) /* XXX: check this */
2540 new_msr
|= (target_ulong
)MSR_HVB
;
2541 switch (excp_model
) {
2542 case POWERPC_EXCP_602
:
2543 case POWERPC_EXCP_603
:
2544 case POWERPC_EXCP_603E
:
2545 case POWERPC_EXCP_G2
:
2547 case POWERPC_EXCP_7x5
:
2549 case POWERPC_EXCP_74xx
:
2552 cpu_abort(env
, "Invalid instruction TLB miss exception\n");
2556 case POWERPC_EXCP_DLTLB
: /* Data load TLB miss */
2557 new_msr
&= ~((target_ulong
)1 << MSR_RI
); /* XXX: check this */
2558 if (lpes1
== 0) /* XXX: check this */
2559 new_msr
|= (target_ulong
)MSR_HVB
;
2560 switch (excp_model
) {
2561 case POWERPC_EXCP_602
:
2562 case POWERPC_EXCP_603
:
2563 case POWERPC_EXCP_603E
:
2564 case POWERPC_EXCP_G2
:
2566 case POWERPC_EXCP_7x5
:
2568 case POWERPC_EXCP_74xx
:
2571 cpu_abort(env
, "Invalid data load TLB miss exception\n");
2575 case POWERPC_EXCP_DSTLB
: /* Data store TLB miss */
2576 new_msr
&= ~((target_ulong
)1 << MSR_RI
); /* XXX: check this */
2577 if (lpes1
== 0) /* XXX: check this */
2578 new_msr
|= (target_ulong
)MSR_HVB
;
2579 switch (excp_model
) {
2580 case POWERPC_EXCP_602
:
2581 case POWERPC_EXCP_603
:
2582 case POWERPC_EXCP_603E
:
2583 case POWERPC_EXCP_G2
:
2585 /* Swap temporary saved registers with GPRs */
2586 if (!(new_msr
& ((target_ulong
)1 << MSR_TGPR
))) {
2587 new_msr
|= (target_ulong
)1 << MSR_TGPR
;
2588 hreg_swap_gpr_tgpr(env
);
2591 case POWERPC_EXCP_7x5
:
2593 #if defined (DEBUG_SOFTWARE_TLB)
2594 if (loglevel
!= 0) {
2595 const unsigned char *es
;
2596 target_ulong
*miss
, *cmp
;
2598 if (excp
== POWERPC_EXCP_IFTLB
) {
2601 miss
= &env
->spr
[SPR_IMISS
];
2602 cmp
= &env
->spr
[SPR_ICMP
];
2604 if (excp
== POWERPC_EXCP_DLTLB
)
2609 miss
= &env
->spr
[SPR_DMISS
];
2610 cmp
= &env
->spr
[SPR_DCMP
];
2612 fprintf(logfile
, "6xx %sTLB miss: %cM " ADDRX
" %cC " ADDRX
2613 " H1 " ADDRX
" H2 " ADDRX
" %08x\n",
2614 es
, en
, *miss
, en
, *cmp
,
2615 env
->spr
[SPR_HASH1
], env
->spr
[SPR_HASH2
],
2619 msr
|= env
->crf
[0] << 28;
2620 msr
|= env
->error_code
; /* key, D/I, S/L bits */
2621 /* Set way using a LRU mechanism */
2622 msr
|= ((env
->last_way
+ 1) & (env
->nb_ways
- 1)) << 17;
2624 case POWERPC_EXCP_74xx
:
2626 #if defined (DEBUG_SOFTWARE_TLB)
2627 if (loglevel
!= 0) {
2628 const unsigned char *es
;
2629 target_ulong
*miss
, *cmp
;
2631 if (excp
== POWERPC_EXCP_IFTLB
) {
2634 miss
= &env
->spr
[SPR_TLBMISS
];
2635 cmp
= &env
->spr
[SPR_PTEHI
];
2637 if (excp
== POWERPC_EXCP_DLTLB
)
2642 miss
= &env
->spr
[SPR_TLBMISS
];
2643 cmp
= &env
->spr
[SPR_PTEHI
];
2645 fprintf(logfile
, "74xx %sTLB miss: %cM " ADDRX
" %cC " ADDRX
2647 es
, en
, *miss
, en
, *cmp
, env
->error_code
);
2650 msr
|= env
->error_code
; /* key bit */
2653 cpu_abort(env
, "Invalid data store TLB miss exception\n");
2657 case POWERPC_EXCP_FPA
: /* Floating-point assist exception */
2659 cpu_abort(env
, "Floating point assist exception "
2660 "is not implemented yet !\n");
2662 case POWERPC_EXCP_DABR
: /* Data address breakpoint */
2664 cpu_abort(env
, "DABR exception is not implemented yet !\n");
2666 case POWERPC_EXCP_IABR
: /* Instruction address breakpoint */
2668 cpu_abort(env
, "IABR exception is not implemented yet !\n");
2670 case POWERPC_EXCP_SMI
: /* System management interrupt */
2672 cpu_abort(env
, "SMI exception is not implemented yet !\n");
2674 case POWERPC_EXCP_THERM
: /* Thermal interrupt */
2676 cpu_abort(env
, "Thermal management exception "
2677 "is not implemented yet !\n");
2679 case POWERPC_EXCP_PERFM
: /* Embedded performance monitor interrupt */
2680 new_msr
&= ~((target_ulong
)1 << MSR_RI
);
2682 new_msr
|= (target_ulong
)MSR_HVB
;
2685 "Performance counter exception is not implemented yet !\n");
2687 case POWERPC_EXCP_VPUA
: /* Vector assist exception */
2689 cpu_abort(env
, "VPU assist exception is not implemented yet !\n");
2691 case POWERPC_EXCP_SOFTP
: /* Soft patch exception */
2694 "970 soft-patch exception is not implemented yet !\n");
2696 case POWERPC_EXCP_MAINT
: /* Maintenance exception */
2699 "970 maintenance exception is not implemented yet !\n");
2701 case POWERPC_EXCP_MEXTBR
: /* Maskable external breakpoint */
2703 cpu_abort(env
, "Maskable external exception "
2704 "is not implemented yet !\n");
2706 case POWERPC_EXCP_NMEXTBR
: /* Non maskable external breakpoint */
2708 cpu_abort(env
, "Non maskable external exception "
2709 "is not implemented yet !\n");
2713 cpu_abort(env
, "Invalid PowerPC exception %d. Aborting\n", excp
);
2716 /* save current instruction location */
2717 env
->spr
[srr0
] = env
->nip
- 4;
2720 /* save next instruction location */
2721 env
->spr
[srr0
] = env
->nip
;
2725 env
->spr
[srr1
] = msr
;
2726 /* If any alternate SRR register are defined, duplicate saved values */
2728 env
->spr
[asrr0
] = env
->spr
[srr0
];
2730 env
->spr
[asrr1
] = env
->spr
[srr1
];
2731 /* If we disactivated any translation, flush TLBs */
2732 if (new_msr
& ((1 << MSR_IR
) | (1 << MSR_DR
)))
2734 /* reload MSR with correct bits */
2735 new_msr
&= ~((target_ulong
)1 << MSR_EE
);
2736 new_msr
&= ~((target_ulong
)1 << MSR_PR
);
2737 new_msr
&= ~((target_ulong
)1 << MSR_FP
);
2738 new_msr
&= ~((target_ulong
)1 << MSR_FE0
);
2739 new_msr
&= ~((target_ulong
)1 << MSR_SE
);
2740 new_msr
&= ~((target_ulong
)1 << MSR_BE
);
2741 new_msr
&= ~((target_ulong
)1 << MSR_FE1
);
2742 new_msr
&= ~((target_ulong
)1 << MSR_IR
);
2743 new_msr
&= ~((target_ulong
)1 << MSR_DR
);
2744 #if 0 /* Fix this: not on all targets */
2745 new_msr
&= ~((target_ulong
)1 << MSR_PMM
);
2747 new_msr
&= ~((target_ulong
)1 << MSR_LE
);
2749 new_msr
|= (target_ulong
)1 << MSR_LE
;
2751 new_msr
&= ~((target_ulong
)1 << MSR_LE
);
2752 /* Jump to handler */
2753 vector
= env
->excp_vectors
[excp
];
2754 if (vector
== (target_ulong
)-1ULL) {
2755 cpu_abort(env
, "Raised an exception without defined vector %d\n",
2758 vector
|= env
->excp_prefix
;
2759 #if defined(TARGET_PPC64)
2760 if (excp_model
== POWERPC_EXCP_BOOKE
) {
2762 new_msr
&= ~((target_ulong
)1 << MSR_CM
);
2763 vector
= (uint32_t)vector
;
2765 new_msr
|= (target_ulong
)1 << MSR_CM
;
2769 new_msr
&= ~((target_ulong
)1 << MSR_SF
);
2770 vector
= (uint32_t)vector
;
2772 new_msr
|= (target_ulong
)1 << MSR_SF
;
2776 /* XXX: we don't use hreg_store_msr here as already have treated
2777 * any special case that could occur. Just store MSR and update hflags
2779 env
->msr
= new_msr
& env
->msr_mask
;
2780 hreg_compute_hflags(env
);
2782 /* Reset exception state */
2783 env
->exception_index
= POWERPC_EXCP_NONE
;
2784 env
->error_code
= 0;
2787 void do_interrupt (CPUState
*env
)
2789 powerpc_excp(env
, env
->excp_model
, env
->exception_index
);
2792 void ppc_hw_interrupt (CPUPPCState
*env
)
2797 if (loglevel
& CPU_LOG_INT
) {
2798 fprintf(logfile
, "%s: %p pending %08x req %08x me %d ee %d\n",
2799 __func__
, env
, env
->pending_interrupts
,
2800 env
->interrupt_request
, (int)msr_me
, (int)msr_ee
);
2803 /* External reset */
2804 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_RESET
)) {
2805 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_RESET
);
2806 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_RESET
);
2809 /* Machine check exception */
2810 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_MCK
)) {
2811 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_MCK
);
2812 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_MCHECK
);
2816 /* External debug exception */
2817 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_DEBUG
)) {
2818 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_DEBUG
);
2819 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_DEBUG
);
2824 /* XXX: find a suitable condition to enable the hypervisor mode */
2825 hdice
= env
->spr
[SPR_LPCR
] & 1;
2829 if ((msr_ee
!= 0 || msr_hv
== 0 || msr_pr
!= 0) && hdice
!= 0) {
2830 /* Hypervisor decrementer exception */
2831 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_HDECR
)) {
2832 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_HDECR
);
2833 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_HDECR
);
2838 /* External critical interrupt */
2839 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_CEXT
)) {
2840 /* Taking a critical external interrupt does not clear the external
2841 * critical interrupt status
2844 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_CEXT
);
2846 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_CRITICAL
);
2851 /* Watchdog timer on embedded PowerPC */
2852 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_WDT
)) {
2853 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_WDT
);
2854 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_WDT
);
2857 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_CDOORBELL
)) {
2858 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_CDOORBELL
);
2859 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_DOORCI
);
2862 /* Fixed interval timer on embedded PowerPC */
2863 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_FIT
)) {
2864 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_FIT
);
2865 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_FIT
);
2868 /* Programmable interval timer on embedded PowerPC */
2869 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_PIT
)) {
2870 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_PIT
);
2871 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_PIT
);
2874 /* Decrementer exception */
2875 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_DECR
)) {
2876 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_DECR
);
2877 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_DECR
);
2880 /* External interrupt */
2881 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_EXT
)) {
2882 /* Taking an external interrupt does not clear the external
2886 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_EXT
);
2888 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_EXTERNAL
);
2891 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_DOORBELL
)) {
2892 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_DOORBELL
);
2893 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_DOORI
);
2896 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_PERFM
)) {
2897 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_PERFM
);
2898 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_PERFM
);
2901 /* Thermal interrupt */
2902 if (env
->pending_interrupts
& (1 << PPC_INTERRUPT_THERM
)) {
2903 env
->pending_interrupts
&= ~(1 << PPC_INTERRUPT_THERM
);
2904 powerpc_excp(env
, env
->excp_model
, POWERPC_EXCP_THERM
);
2909 #endif /* !CONFIG_USER_ONLY */
2911 void cpu_dump_rfi (target_ulong RA
, target_ulong msr
)
2921 fprintf(f
, "Return from exception at " ADDRX
" with flags " ADDRX
"\n",
2925 void cpu_ppc_reset (void *opaque
)
2931 msr
= (target_ulong
)0;
2933 /* XXX: find a suitable condition to enable the hypervisor mode */
2934 msr
|= (target_ulong
)MSR_HVB
;
2936 msr
|= (target_ulong
)0 << MSR_AP
; /* TO BE CHECKED */
2937 msr
|= (target_ulong
)0 << MSR_SA
; /* TO BE CHECKED */
2938 msr
|= (target_ulong
)1 << MSR_EP
;
2939 #if defined (DO_SINGLE_STEP) && 0
2940 /* Single step trace mode */
2941 msr
|= (target_ulong
)1 << MSR_SE
;
2942 msr
|= (target_ulong
)1 << MSR_BE
;
2944 #if defined(CONFIG_USER_ONLY)
2945 msr
|= (target_ulong
)1 << MSR_FP
; /* Allow floating point usage */
2946 msr
|= (target_ulong
)1 << MSR_PR
;
2948 env
->nip
= env
->hreset_vector
| env
->excp_prefix
;
2949 if (env
->mmu_model
!= POWERPC_MMU_REAL
)
2950 ppc_tlb_invalidate_all(env
);
2953 hreg_compute_hflags(env
);
2954 env
->reserve
= (target_ulong
)-1ULL;
2955 /* Be sure no exception or interrupt is pending */
2956 env
->pending_interrupts
= 0;
2957 env
->exception_index
= POWERPC_EXCP_NONE
;
2958 env
->error_code
= 0;
2959 /* Flush all TLBs */
2963 CPUPPCState
*cpu_ppc_init (const char *cpu_model
)
2966 const ppc_def_t
*def
;
2968 def
= cpu_ppc_find_by_name(cpu_model
);
2972 env
= qemu_mallocz(sizeof(CPUPPCState
));
2976 ppc_translate_init();
2977 env
->cpu_model_str
= cpu_model
;
2978 cpu_ppc_register_internal(env
, def
);
2983 void cpu_ppc_close (CPUPPCState
*env
)
2985 /* Should also remove all opcode tables... */