Annotation of qemu/target-ppc/helper.c, revision 1.1.1.4

1.1       root        1: /*
                      2:  *  PowerPC emulation helpers for qemu.
1.1.1.4 ! root        3:  *
        !             4:  *  Copyright (c) 2003-2007 Jocelyn Mayer
1.1       root        5:  *
                      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.
                     10:  *
                     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.
                     15:  *
                     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
                     19:  */
                     20: #include <stdarg.h>
                     21: #include <stdlib.h>
                     22: #include <stdio.h>
                     23: #include <string.h>
                     24: #include <inttypes.h>
                     25: #include <signal.h>
                     26: #include <assert.h>
                     27: 
                     28: #include "cpu.h"
                     29: #include "exec-all.h"
1.1.1.4 ! root       30: #include "helper_regs.h"
1.1       root       31: 
                     32: //#define DEBUG_MMU
                     33: //#define DEBUG_BATS
1.1.1.4 ! root       34: //#define DEBUG_SLB
        !            35: //#define DEBUG_SOFTWARE_TLB
        !            36: //#define DUMP_PAGE_TABLES
1.1       root       37: //#define DEBUG_EXCEPTIONS
                     38: //#define FLUSH_ALL_TLBS
                     39: 
                     40: /*****************************************************************************/
                     41: /* PowerPC MMU emulation */
                     42: 
1.1.1.4 ! root       43: #if defined(CONFIG_USER_ONLY)
        !            44: int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
        !            45:                               int mmu_idx, int is_softmmu)
1.1.1.2   root       46: {
                     47:     int exception, error_code;
1.1.1.4 ! root       48: 
1.1.1.2   root       49:     if (rw == 2) {
1.1.1.4 ! root       50:         exception = POWERPC_EXCP_ISI;
        !            51:         error_code = 0x40000000;
1.1.1.2   root       52:     } else {
1.1.1.4 ! root       53:         exception = POWERPC_EXCP_DSI;
        !            54:         error_code = 0x40000000;
1.1.1.2   root       55:         if (rw)
                     56:             error_code |= 0x02000000;
                     57:         env->spr[SPR_DAR] = address;
                     58:         env->spr[SPR_DSISR] = error_code;
                     59:     }
                     60:     env->exception_index = exception;
                     61:     env->error_code = error_code;
1.1.1.4 ! root       62: 
1.1.1.2   root       63:     return 1;
                     64: }
1.1.1.4 ! root       65: 
        !            66: target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1.1.1.2   root       67: {
                     68:     return addr;
                     69: }
1.1.1.4 ! root       70: 
        !            71: #else
        !            72: /* Common routines used by software and hardware TLBs emulation */
        !            73: static always_inline int pte_is_valid (target_ulong pte0)
        !            74: {
        !            75:     return pte0 & 0x80000000 ? 1 : 0;
        !            76: }
        !            77: 
        !            78: static always_inline void pte_invalidate (target_ulong *pte0)
        !            79: {
        !            80:     *pte0 &= ~0x80000000;
        !            81: }
        !            82: 
        !            83: #if defined(TARGET_PPC64)
        !            84: static always_inline int pte64_is_valid (target_ulong pte0)
        !            85: {
        !            86:     return pte0 & 0x0000000000000001ULL ? 1 : 0;
        !            87: }
        !            88: 
        !            89: static always_inline void pte64_invalidate (target_ulong *pte0)
        !            90: {
        !            91:     *pte0 &= ~0x0000000000000001ULL;
        !            92: }
        !            93: #endif
        !            94: 
        !            95: #define PTE_PTEM_MASK 0x7FFFFFBF
        !            96: #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
        !            97: #if defined(TARGET_PPC64)
        !            98: #define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
        !            99: #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
        !           100: #endif
        !           101: 
        !           102: static always_inline int pp_check (int key, int pp, int nx)
        !           103: {
        !           104:     int access;
        !           105: 
        !           106:     /* Compute access rights */
        !           107:     /* When pp is 3/7, the result is undefined. Set it to noaccess */
        !           108:     access = 0;
        !           109:     if (key == 0) {
        !           110:         switch (pp) {
        !           111:         case 0x0:
        !           112:         case 0x1:
        !           113:         case 0x2:
        !           114:             access |= PAGE_WRITE;
        !           115:             /* No break here */
        !           116:         case 0x3:
        !           117:         case 0x6:
        !           118:             access |= PAGE_READ;
        !           119:             break;
        !           120:         }
        !           121:     } else {
        !           122:         switch (pp) {
        !           123:         case 0x0:
        !           124:         case 0x6:
        !           125:             access = 0;
        !           126:             break;
        !           127:         case 0x1:
        !           128:         case 0x3:
        !           129:             access = PAGE_READ;
        !           130:             break;
        !           131:         case 0x2:
        !           132:             access = PAGE_READ | PAGE_WRITE;
        !           133:             break;
        !           134:         }
        !           135:     }
        !           136:     if (nx == 0)
        !           137:         access |= PAGE_EXEC;
        !           138: 
        !           139:     return access;
        !           140: }
        !           141: 
        !           142: static always_inline int check_prot (int prot, int rw, int access_type)
        !           143: {
        !           144:     int ret;
        !           145: 
        !           146:     if (access_type == ACCESS_CODE) {
        !           147:         if (prot & PAGE_EXEC)
        !           148:             ret = 0;
        !           149:         else
        !           150:             ret = -2;
        !           151:     } else if (rw) {
        !           152:         if (prot & PAGE_WRITE)
        !           153:             ret = 0;
        !           154:         else
        !           155:             ret = -2;
        !           156:     } else {
        !           157:         if (prot & PAGE_READ)
        !           158:             ret = 0;
        !           159:         else
        !           160:             ret = -2;
        !           161:     }
        !           162: 
        !           163:     return ret;
        !           164: }
        !           165: 
        !           166: static always_inline int _pte_check (mmu_ctx_t *ctx, int is_64b,
        !           167:                                      target_ulong pte0, target_ulong pte1,
        !           168:                                      int h, int rw, int type)
        !           169: {
        !           170:     target_ulong ptem, mmask;
        !           171:     int access, ret, pteh, ptev, pp;
        !           172: 
        !           173:     access = 0;
        !           174:     ret = -1;
        !           175:     /* Check validity and table match */
        !           176: #if defined(TARGET_PPC64)
        !           177:     if (is_64b) {
        !           178:         ptev = pte64_is_valid(pte0);
        !           179:         pteh = (pte0 >> 1) & 1;
        !           180:     } else
        !           181: #endif
        !           182:     {
        !           183:         ptev = pte_is_valid(pte0);
        !           184:         pteh = (pte0 >> 6) & 1;
        !           185:     }
        !           186:     if (ptev && h == pteh) {
        !           187:         /* Check vsid & api */
        !           188: #if defined(TARGET_PPC64)
        !           189:         if (is_64b) {
        !           190:             ptem = pte0 & PTE64_PTEM_MASK;
        !           191:             mmask = PTE64_CHECK_MASK;
        !           192:             pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
        !           193:             ctx->nx |= (pte1 >> 2) & 1; /* No execute bit */
        !           194:             ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
        !           195:         } else
        !           196: #endif
        !           197:         {
        !           198:             ptem = pte0 & PTE_PTEM_MASK;
        !           199:             mmask = PTE_CHECK_MASK;
        !           200:             pp = pte1 & 0x00000003;
        !           201:         }
        !           202:         if (ptem == ctx->ptem) {
        !           203:             if (ctx->raddr != (target_phys_addr_t)-1ULL) {
        !           204:                 /* all matches should have equal RPN, WIMG & PP */
        !           205:                 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
        !           206:                     if (loglevel != 0)
        !           207:                         fprintf(logfile, "Bad RPN/WIMG/PP\n");
        !           208:                     return -3;
        !           209:                 }
        !           210:             }
        !           211:             /* Compute access rights */
        !           212:             access = pp_check(ctx->key, pp, ctx->nx);
        !           213:             /* Keep the matching PTE informations */
        !           214:             ctx->raddr = pte1;
        !           215:             ctx->prot = access;
        !           216:             ret = check_prot(ctx->prot, rw, type);
        !           217:             if (ret == 0) {
        !           218:                 /* Access granted */
        !           219: #if defined (DEBUG_MMU)
        !           220:                 if (loglevel != 0)
        !           221:                     fprintf(logfile, "PTE access granted !\n");
        !           222: #endif
        !           223:             } else {
        !           224:                 /* Access right violation */
        !           225: #if defined (DEBUG_MMU)
        !           226:                 if (loglevel != 0)
        !           227:                     fprintf(logfile, "PTE access rejected\n");
        !           228: #endif
        !           229:             }
        !           230:         }
        !           231:     }
        !           232: 
        !           233:     return ret;
        !           234: }
        !           235: 
        !           236: static always_inline int pte32_check (mmu_ctx_t *ctx,
        !           237:                                       target_ulong pte0, target_ulong pte1,
        !           238:                                       int h, int rw, int type)
        !           239: {
        !           240:     return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
        !           241: }
        !           242: 
        !           243: #if defined(TARGET_PPC64)
        !           244: static always_inline int pte64_check (mmu_ctx_t *ctx,
        !           245:                                       target_ulong pte0, target_ulong pte1,
        !           246:                                       int h, int rw, int type)
        !           247: {
        !           248:     return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
        !           249: }
        !           250: #endif
        !           251: 
        !           252: static always_inline int pte_update_flags (mmu_ctx_t *ctx, target_ulong *pte1p,
        !           253:                                            int ret, int rw)
        !           254: {
        !           255:     int store = 0;
        !           256: 
        !           257:     /* Update page flags */
        !           258:     if (!(*pte1p & 0x00000100)) {
        !           259:         /* Update accessed flag */
        !           260:         *pte1p |= 0x00000100;
        !           261:         store = 1;
        !           262:     }
        !           263:     if (!(*pte1p & 0x00000080)) {
        !           264:         if (rw == 1 && ret == 0) {
        !           265:             /* Update changed flag */
        !           266:             *pte1p |= 0x00000080;
        !           267:             store = 1;
        !           268:         } else {
        !           269:             /* Force page fault for first write access */
        !           270:             ctx->prot &= ~PAGE_WRITE;
        !           271:         }
        !           272:     }
        !           273: 
        !           274:     return store;
        !           275: }
        !           276: 
        !           277: /* Software driven TLB helpers */
        !           278: static always_inline int ppc6xx_tlb_getnum (CPUState *env, target_ulong eaddr,
        !           279:                                             int way, int is_code)
        !           280: {
        !           281:     int nr;
        !           282: 
        !           283:     /* Select TLB num in a way from address */
        !           284:     nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
        !           285:     /* Select TLB way */
        !           286:     nr += env->tlb_per_way * way;
        !           287:     /* 6xx have separate TLBs for instructions and data */
        !           288:     if (is_code && env->id_tlbs == 1)
        !           289:         nr += env->nb_tlb;
        !           290: 
        !           291:     return nr;
        !           292: }
        !           293: 
        !           294: static always_inline void ppc6xx_tlb_invalidate_all (CPUState *env)
        !           295: {
        !           296:     ppc6xx_tlb_t *tlb;
        !           297:     int nr, max;
        !           298: 
        !           299: #if defined (DEBUG_SOFTWARE_TLB) && 0
        !           300:     if (loglevel != 0) {
        !           301:         fprintf(logfile, "Invalidate all TLBs\n");
        !           302:     }
        !           303: #endif
        !           304:     /* Invalidate all defined software TLB */
        !           305:     max = env->nb_tlb;
        !           306:     if (env->id_tlbs == 1)
        !           307:         max *= 2;
        !           308:     for (nr = 0; nr < max; nr++) {
        !           309:         tlb = &env->tlb[nr].tlb6;
        !           310:         pte_invalidate(&tlb->pte0);
        !           311:     }
        !           312:     tlb_flush(env, 1);
        !           313: }
        !           314: 
        !           315: static always_inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
        !           316:                                                         target_ulong eaddr,
        !           317:                                                         int is_code,
        !           318:                                                         int match_epn)
        !           319: {
        !           320: #if !defined(FLUSH_ALL_TLBS)
        !           321:     ppc6xx_tlb_t *tlb;
        !           322:     int way, nr;
        !           323: 
        !           324:     /* Invalidate ITLB + DTLB, all ways */
        !           325:     for (way = 0; way < env->nb_ways; way++) {
        !           326:         nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
        !           327:         tlb = &env->tlb[nr].tlb6;
        !           328:         if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
        !           329: #if defined (DEBUG_SOFTWARE_TLB)
        !           330:             if (loglevel != 0) {
        !           331:                 fprintf(logfile, "TLB invalidate %d/%d " ADDRX "\n",
        !           332:                         nr, env->nb_tlb, eaddr);
        !           333:             }
        !           334: #endif
        !           335:             pte_invalidate(&tlb->pte0);
        !           336:             tlb_flush_page(env, tlb->EPN);
        !           337:         }
        !           338:     }
1.1.1.2   root      339: #else
1.1.1.4 ! root      340:     /* XXX: PowerPC specification say this is valid as well */
        !           341:     ppc6xx_tlb_invalidate_all(env);
        !           342: #endif
        !           343: }
        !           344: 
        !           345: static always_inline void ppc6xx_tlb_invalidate_virt (CPUState *env,
        !           346:                                                       target_ulong eaddr,
        !           347:                                                       int is_code)
        !           348: {
        !           349:     __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
        !           350: }
        !           351: 
        !           352: void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
        !           353:                        target_ulong pte0, target_ulong pte1)
        !           354: {
        !           355:     ppc6xx_tlb_t *tlb;
        !           356:     int nr;
        !           357: 
        !           358:     nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
        !           359:     tlb = &env->tlb[nr].tlb6;
        !           360: #if defined (DEBUG_SOFTWARE_TLB)
        !           361:     if (loglevel != 0) {
        !           362:         fprintf(logfile, "Set TLB %d/%d EPN " ADDRX " PTE0 " ADDRX
        !           363:                 " PTE1 " ADDRX "\n", nr, env->nb_tlb, EPN, pte0, pte1);
        !           364:     }
        !           365: #endif
        !           366:     /* Invalidate any pending reference in Qemu for this virtual address */
        !           367:     __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
        !           368:     tlb->pte0 = pte0;
        !           369:     tlb->pte1 = pte1;
        !           370:     tlb->EPN = EPN;
        !           371:     /* Store last way for LRU mechanism */
        !           372:     env->last_way = way;
        !           373: }
        !           374: 
        !           375: static always_inline int ppc6xx_tlb_check (CPUState *env, mmu_ctx_t *ctx,
        !           376:                                            target_ulong eaddr, int rw,
        !           377:                                            int access_type)
        !           378: {
        !           379:     ppc6xx_tlb_t *tlb;
        !           380:     int nr, best, way;
        !           381:     int ret;
        !           382: 
        !           383:     best = -1;
        !           384:     ret = -1; /* No TLB found */
        !           385:     for (way = 0; way < env->nb_ways; way++) {
        !           386:         nr = ppc6xx_tlb_getnum(env, eaddr, way,
        !           387:                                access_type == ACCESS_CODE ? 1 : 0);
        !           388:         tlb = &env->tlb[nr].tlb6;
        !           389:         /* This test "emulates" the PTE index match for hardware TLBs */
        !           390:         if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
        !           391: #if defined (DEBUG_SOFTWARE_TLB)
        !           392:             if (loglevel != 0) {
        !           393:                 fprintf(logfile, "TLB %d/%d %s [" ADDRX " " ADDRX
        !           394:                         "] <> " ADDRX "\n",
        !           395:                         nr, env->nb_tlb,
        !           396:                         pte_is_valid(tlb->pte0) ? "valid" : "inval",
        !           397:                         tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
        !           398:             }
        !           399: #endif
        !           400:             continue;
        !           401:         }
        !           402: #if defined (DEBUG_SOFTWARE_TLB)
        !           403:         if (loglevel != 0) {
        !           404:             fprintf(logfile, "TLB %d/%d %s " ADDRX " <> " ADDRX " " ADDRX
        !           405:                     " %c %c\n",
        !           406:                     nr, env->nb_tlb,
        !           407:                     pte_is_valid(tlb->pte0) ? "valid" : "inval",
        !           408:                     tlb->EPN, eaddr, tlb->pte1,
        !           409:                     rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
        !           410:         }
        !           411: #endif
        !           412:         switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
        !           413:         case -3:
        !           414:             /* TLB inconsistency */
        !           415:             return -1;
        !           416:         case -2:
        !           417:             /* Access violation */
        !           418:             ret = -2;
        !           419:             best = nr;
        !           420:             break;
        !           421:         case -1:
        !           422:         default:
        !           423:             /* No match */
        !           424:             break;
        !           425:         case 0:
        !           426:             /* access granted */
        !           427:             /* XXX: we should go on looping to check all TLBs consistency
        !           428:              *      but we can speed-up the whole thing as the
        !           429:              *      result would be undefined if TLBs are not consistent.
        !           430:              */
        !           431:             ret = 0;
        !           432:             best = nr;
        !           433:             goto done;
        !           434:         }
        !           435:     }
        !           436:     if (best != -1) {
        !           437:     done:
        !           438: #if defined (DEBUG_SOFTWARE_TLB)
        !           439:         if (loglevel != 0) {
        !           440:             fprintf(logfile, "found TLB at addr " PADDRX " prot=%01x ret=%d\n",
        !           441:                     ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
        !           442:         }
        !           443: #endif
        !           444:         /* Update page flags */
        !           445:         pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
        !           446:     }
        !           447: 
        !           448:     return ret;
        !           449: }
        !           450: 
1.1       root      451: /* Perform BAT hit & translation */
1.1.1.4 ! root      452: static always_inline void bat_size_prot (CPUState *env, target_ulong *blp,
        !           453:                                          int *validp, int *protp,
        !           454:                                          target_ulong *BATu, target_ulong *BATl)
        !           455: {
        !           456:     target_ulong bl;
        !           457:     int pp, valid, prot;
        !           458: 
        !           459:     bl = (*BATu & 0x00001FFC) << 15;
        !           460:     valid = 0;
        !           461:     prot = 0;
        !           462:     if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
        !           463:         ((msr_pr != 0) && (*BATu & 0x00000001))) {
        !           464:         valid = 1;
        !           465:         pp = *BATl & 0x00000003;
        !           466:         if (pp != 0) {
        !           467:             prot = PAGE_READ | PAGE_EXEC;
        !           468:             if (pp == 0x2)
        !           469:                 prot |= PAGE_WRITE;
        !           470:         }
        !           471:     }
        !           472:     *blp = bl;
        !           473:     *validp = valid;
        !           474:     *protp = prot;
        !           475: }
        !           476: 
        !           477: static always_inline void bat_601_size_prot (CPUState *env,target_ulong *blp,
        !           478:                                              int *validp, int *protp,
        !           479:                                              target_ulong *BATu,
        !           480:                                              target_ulong *BATl)
1.1       root      481: {
1.1.1.4 ! root      482:     target_ulong bl;
        !           483:     int key, pp, valid, prot;
        !           484: 
        !           485:     bl = (*BATl & 0x0000003F) << 17;
        !           486: #if defined (DEBUG_BATS)
        !           487:     if (loglevel != 0) {
        !           488:         fprintf(logfile, "b %02x ==> bl " ADDRX " msk " ADDRX "\n",
        !           489:                 (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
        !           490:     }
        !           491: #endif
        !           492:     prot = 0;
        !           493:     valid = (*BATl >> 6) & 1;
        !           494:     if (valid) {
        !           495:         pp = *BATu & 0x00000003;
        !           496:         if (msr_pr == 0)
        !           497:             key = (*BATu >> 3) & 1;
        !           498:         else
        !           499:             key = (*BATu >> 2) & 1;
        !           500:         prot = pp_check(key, pp, 0);
        !           501:     }
        !           502:     *blp = bl;
        !           503:     *validp = valid;
        !           504:     *protp = prot;
        !           505: }
        !           506: 
        !           507: static always_inline int get_bat (CPUState *env, mmu_ctx_t *ctx,
        !           508:                                   target_ulong virtual, int rw, int type)
        !           509: {
        !           510:     target_ulong *BATlt, *BATut, *BATu, *BATl;
        !           511:     target_ulong base, BEPIl, BEPIu, bl;
        !           512:     int i, valid, prot;
1.1       root      513:     int ret = -1;
                    514: 
                    515: #if defined (DEBUG_BATS)
1.1.1.4 ! root      516:     if (loglevel != 0) {
        !           517:         fprintf(logfile, "%s: %cBAT v " ADDRX "\n", __func__,
        !           518:                 type == ACCESS_CODE ? 'I' : 'D', virtual);
1.1       root      519:     }
                    520: #endif
                    521:     switch (type) {
                    522:     case ACCESS_CODE:
                    523:         BATlt = env->IBAT[1];
                    524:         BATut = env->IBAT[0];
                    525:         break;
                    526:     default:
                    527:         BATlt = env->DBAT[1];
                    528:         BATut = env->DBAT[0];
                    529:         break;
                    530:     }
                    531:     base = virtual & 0xFFFC0000;
1.1.1.4 ! root      532:     for (i = 0; i < env->nb_BATs; i++) {
1.1       root      533:         BATu = &BATut[i];
                    534:         BATl = &BATlt[i];
                    535:         BEPIu = *BATu & 0xF0000000;
                    536:         BEPIl = *BATu & 0x0FFE0000;
1.1.1.4 ! root      537:         if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
        !           538:             bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
        !           539:         } else {
        !           540:             bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
        !           541:         }
1.1       root      542: #if defined (DEBUG_BATS)
1.1.1.4 ! root      543:         if (loglevel != 0) {
        !           544:             fprintf(logfile, "%s: %cBAT%d v " ADDRX " BATu " ADDRX
        !           545:                     " BATl " ADDRX "\n", __func__,
        !           546:                     type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
1.1       root      547:         }
                    548: #endif
                    549:         if ((virtual & 0xF0000000) == BEPIu &&
                    550:             ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
                    551:             /* BAT matches */
1.1.1.4 ! root      552:             if (valid != 0) {
1.1       root      553:                 /* Get physical address */
1.1.1.4 ! root      554:                 ctx->raddr = (*BATl & 0xF0000000) |
1.1       root      555:                     ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
                    556:                     (virtual & 0x0001F000);
1.1.1.4 ! root      557:                 /* Compute access rights */
        !           558:                 ctx->prot = prot;
        !           559:                 ret = check_prot(ctx->prot, rw, type);
1.1       root      560: #if defined (DEBUG_BATS)
1.1.1.4 ! root      561:                 if (ret == 0 && loglevel != 0) {
        !           562:                     fprintf(logfile, "BAT %d match: r " PADDRX " prot=%c%c\n",
        !           563:                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
        !           564:                             ctx->prot & PAGE_WRITE ? 'W' : '-');
1.1       root      565:                 }
                    566: #endif
                    567:                 break;
                    568:             }
                    569:         }
                    570:     }
                    571:     if (ret < 0) {
                    572: #if defined (DEBUG_BATS)
1.1.1.4 ! root      573:         if (loglevel != 0) {
        !           574:             fprintf(logfile, "no BAT match for " ADDRX ":\n", virtual);
        !           575:             for (i = 0; i < 4; i++) {
        !           576:                 BATu = &BATut[i];
        !           577:                 BATl = &BATlt[i];
        !           578:                 BEPIu = *BATu & 0xF0000000;
        !           579:                 BEPIl = *BATu & 0x0FFE0000;
        !           580:                 bl = (*BATu & 0x00001FFC) << 15;
        !           581:                 fprintf(logfile, "%s: %cBAT%d v " ADDRX " BATu " ADDRX
        !           582:                         " BATl " ADDRX " \n\t" ADDRX " " ADDRX " " ADDRX "\n",
        !           583:                         __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
        !           584:                         *BATu, *BATl, BEPIu, BEPIl, bl);
        !           585:             }
1.1       root      586:         }
                    587: #endif
                    588:     }
1.1.1.4 ! root      589: 
1.1       root      590:     /* No hit */
                    591:     return ret;
                    592: }
                    593: 
                    594: /* PTE table lookup */
1.1.1.4 ! root      595: static always_inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h,
        !           596:                                     int rw, int type)
1.1       root      597: {
1.1.1.4 ! root      598:     target_ulong base, pte0, pte1;
        !           599:     int i, good = -1;
        !           600:     int ret, r;
1.1       root      601: 
1.1.1.4 ! root      602:     ret = -1; /* No entry found */
        !           603:     base = ctx->pg_addr[h];
1.1       root      604:     for (i = 0; i < 8; i++) {
1.1.1.4 ! root      605: #if defined(TARGET_PPC64)
        !           606:         if (is_64b) {
        !           607:             pte0 = ldq_phys(base + (i * 16));
        !           608:             pte1 =  ldq_phys(base + (i * 16) + 8);
        !           609:             r = pte64_check(ctx, pte0, pte1, h, rw, type);
1.1       root      610: #if defined (DEBUG_MMU)
1.1.1.4 ! root      611:             if (loglevel != 0) {
        !           612:                 fprintf(logfile, "Load pte from " ADDRX " => " ADDRX " " ADDRX
        !           613:                         " %d %d %d " ADDRX "\n",
        !           614:                         base + (i * 16), pte0, pte1,
        !           615:                         (int)(pte0 & 1), h, (int)((pte0 >> 1) & 1),
        !           616:                         ctx->ptem);
        !           617:             }
1.1       root      618: #endif
1.1.1.4 ! root      619:         } else
1.1       root      620: #endif
1.1.1.4 ! root      621:         {
        !           622:             pte0 = ldl_phys(base + (i * 8));
        !           623:             pte1 =  ldl_phys(base + (i * 8) + 4);
        !           624:             r = pte32_check(ctx, pte0, pte1, h, rw, type);
        !           625: #if defined (DEBUG_MMU)
        !           626:             if (loglevel != 0) {
        !           627:                 fprintf(logfile, "Load pte from " ADDRX " => " ADDRX " " ADDRX
        !           628:                         " %d %d %d " ADDRX "\n",
        !           629:                         base + (i * 8), pte0, pte1,
        !           630:                         (int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1),
        !           631:                         ctx->ptem);
1.1       root      632:             }
1.1.1.4 ! root      633: #endif
        !           634:         }
        !           635:         switch (r) {
        !           636:         case -3:
        !           637:             /* PTE inconsistency */
        !           638:             return -1;
        !           639:         case -2:
        !           640:             /* Access violation */
        !           641:             ret = -2;
        !           642:             good = i;
        !           643:             break;
        !           644:         case -1:
        !           645:         default:
        !           646:             /* No PTE match */
        !           647:             break;
        !           648:         case 0:
        !           649:             /* access granted */
        !           650:             /* XXX: we should go on looping to check all PTEs consistency
        !           651:              *      but if we can speed-up the whole thing as the
        !           652:              *      result would be undefined if PTEs are not consistent.
        !           653:              */
        !           654:             ret = 0;
        !           655:             good = i;
        !           656:             goto done;
1.1       root      657:         }
                    658:     }
                    659:     if (good != -1) {
1.1.1.4 ! root      660:     done:
1.1       root      661: #if defined (DEBUG_MMU)
1.1.1.4 ! root      662:         if (loglevel != 0) {
        !           663:             fprintf(logfile, "found PTE at addr " PADDRX " prot=%01x ret=%d\n",
        !           664:                     ctx->raddr, ctx->prot, ret);
        !           665:         }
1.1       root      666: #endif
                    667:         /* Update page flags */
1.1.1.4 ! root      668:         pte1 = ctx->raddr;
        !           669:         if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
        !           670: #if defined(TARGET_PPC64)
        !           671:             if (is_64b) {
        !           672:                 stq_phys_notdirty(base + (good * 16) + 8, pte1);
        !           673:             } else
        !           674: #endif
        !           675:             {
        !           676:                 stl_phys_notdirty(base + (good * 8) + 4, pte1);
1.1       root      677:             }
                    678:         }
                    679:     }
                    680: 
                    681:     return ret;
                    682: }
                    683: 
1.1.1.4 ! root      684: static always_inline int find_pte32 (mmu_ctx_t *ctx, int h, int rw, int type)
1.1       root      685: {
1.1.1.4 ! root      686:     return _find_pte(ctx, 0, h, rw, type);
1.1       root      687: }
                    688: 
1.1.1.4 ! root      689: #if defined(TARGET_PPC64)
        !           690: static always_inline int find_pte64 (mmu_ctx_t *ctx, int h, int rw, int type)
1.1       root      691: {
1.1.1.4 ! root      692:     return _find_pte(ctx, 1, h, rw, type);
        !           693: }
        !           694: #endif
1.1       root      695: 
1.1.1.4 ! root      696: static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx,
        !           697:                                    int h, int rw, int type)
        !           698: {
        !           699: #if defined(TARGET_PPC64)
        !           700:     if (env->mmu_model & POWERPC_MMU_64)
        !           701:         return find_pte64(ctx, h, rw, type);
1.1       root      702: #endif
1.1.1.4 ! root      703: 
        !           704:     return find_pte32(ctx, h, rw, type);
        !           705: }
        !           706: 
        !           707: #if defined(TARGET_PPC64)
        !           708: static always_inline int slb_is_valid (uint64_t slb64)
        !           709: {
        !           710:     return slb64 & 0x0000000008000000ULL ? 1 : 0;
        !           711: }
        !           712: 
        !           713: static always_inline void slb_invalidate (uint64_t *slb64)
        !           714: {
        !           715:     *slb64 &= ~0x0000000008000000ULL;
        !           716: }
        !           717: 
        !           718: static always_inline int slb_lookup (CPUPPCState *env, target_ulong eaddr,
        !           719:                                      target_ulong *vsid,
        !           720:                                      target_ulong *page_mask, int *attr)
        !           721: {
        !           722:     target_phys_addr_t sr_base;
        !           723:     target_ulong mask;
        !           724:     uint64_t tmp64;
        !           725:     uint32_t tmp;
        !           726:     int n, ret;
        !           727: 
        !           728:     ret = -5;
        !           729:     sr_base = env->spr[SPR_ASR];
        !           730: #if defined(DEBUG_SLB)
        !           731:     if (loglevel != 0) {
        !           732:         fprintf(logfile, "%s: eaddr " ADDRX " base " PADDRX "\n",
        !           733:                 __func__, eaddr, sr_base);
        !           734:     }
1.1       root      735: #endif
1.1.1.4 ! root      736:     mask = 0x0000000000000000ULL; /* Avoid gcc warning */
        !           737:     for (n = 0; n < env->slb_nr; n++) {
        !           738:         tmp64 = ldq_phys(sr_base);
        !           739:         tmp = ldl_phys(sr_base + 8);
        !           740: #if defined(DEBUG_SLB)
        !           741:         if (loglevel != 0) {
        !           742:             fprintf(logfile, "%s: seg %d " PADDRX " %016" PRIx64 " %08"
        !           743:                     PRIx32 "\n", __func__, n, sr_base, tmp64, tmp);
        !           744:         }
1.1       root      745: #endif
1.1.1.4 ! root      746:         if (slb_is_valid(tmp64)) {
        !           747:             /* SLB entry is valid */
        !           748:             switch (tmp64 & 0x0000000006000000ULL) {
        !           749:             case 0x0000000000000000ULL:
        !           750:                 /* 256 MB segment */
        !           751:                 mask = 0xFFFFFFFFF0000000ULL;
        !           752:                 break;
        !           753:             case 0x0000000002000000ULL:
        !           754:                 /* 1 TB segment */
        !           755:                 mask = 0xFFFF000000000000ULL;
        !           756:                 break;
        !           757:             case 0x0000000004000000ULL:
        !           758:             case 0x0000000006000000ULL:
        !           759:                 /* Reserved => segment is invalid */
        !           760:                 continue;
1.1       root      761:             }
1.1.1.4 ! root      762:             if ((eaddr & mask) == (tmp64 & mask)) {
        !           763:                 /* SLB match */
        !           764:                 *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
        !           765:                 *page_mask = ~mask;
        !           766:                 *attr = tmp & 0xFF;
        !           767:                 ret = n;
        !           768:                 break;
        !           769:             }
        !           770:         }
        !           771:         sr_base += 12;
        !           772:     }
        !           773: 
        !           774:     return ret;
        !           775: }
        !           776: 
        !           777: void ppc_slb_invalidate_all (CPUPPCState *env)
        !           778: {
        !           779:     target_phys_addr_t sr_base;
        !           780:     uint64_t tmp64;
        !           781:     int n, do_invalidate;
        !           782: 
        !           783:     do_invalidate = 0;
        !           784:     sr_base = env->spr[SPR_ASR];
        !           785:     /* XXX: Warning: slbia never invalidates the first segment */
        !           786:     for (n = 1; n < env->slb_nr; n++) {
        !           787:         tmp64 = ldq_phys(sr_base);
        !           788:         if (slb_is_valid(tmp64)) {
        !           789:             slb_invalidate(&tmp64);
        !           790:             stq_phys(sr_base, tmp64);
        !           791:             /* XXX: given the fact that segment size is 256 MB or 1TB,
        !           792:              *      and we still don't have a tlb_flush_mask(env, n, mask)
        !           793:              *      in Qemu, we just invalidate all TLBs
        !           794:              */
        !           795:             do_invalidate = 1;
        !           796:         }
        !           797:         sr_base += 12;
        !           798:     }
        !           799:     if (do_invalidate)
        !           800:         tlb_flush(env, 1);
        !           801: }
        !           802: 
        !           803: void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
        !           804: {
        !           805:     target_phys_addr_t sr_base;
        !           806:     target_ulong vsid, page_mask;
        !           807:     uint64_t tmp64;
        !           808:     int attr;
        !           809:     int n;
        !           810: 
        !           811:     n = slb_lookup(env, T0, &vsid, &page_mask, &attr);
        !           812:     if (n >= 0) {
        !           813:         sr_base = env->spr[SPR_ASR];
        !           814:         sr_base += 12 * n;
        !           815:         tmp64 = ldq_phys(sr_base);
        !           816:         if (slb_is_valid(tmp64)) {
        !           817:             slb_invalidate(&tmp64);
        !           818:             stq_phys(sr_base, tmp64);
        !           819:             /* XXX: given the fact that segment size is 256 MB or 1TB,
        !           820:              *      and we still don't have a tlb_flush_mask(env, n, mask)
        !           821:              *      in Qemu, we just invalidate all TLBs
        !           822:              */
        !           823:             tlb_flush(env, 1);
1.1       root      824:         }
1.1.1.4 ! root      825:     }
        !           826: }
        !           827: 
        !           828: target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
        !           829: {
        !           830:     target_phys_addr_t sr_base;
        !           831:     target_ulong rt;
        !           832:     uint64_t tmp64;
        !           833:     uint32_t tmp;
        !           834: 
        !           835:     sr_base = env->spr[SPR_ASR];
        !           836:     sr_base += 12 * slb_nr;
        !           837:     tmp64 = ldq_phys(sr_base);
        !           838:     tmp = ldl_phys(sr_base + 8);
        !           839:     if (tmp64 & 0x0000000008000000ULL) {
        !           840:         /* SLB entry is valid */
        !           841:         /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
        !           842:         rt = tmp >> 8;             /* 65:88 => 40:63 */
        !           843:         rt |= (tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
        !           844:         /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
        !           845:         rt |= ((tmp >> 4) & 0xF) << 27;
1.1       root      846:     } else {
1.1.1.4 ! root      847:         rt = 0;
        !           848:     }
        !           849: #if defined(DEBUG_SLB)
        !           850:     if (loglevel != 0) {
        !           851:         fprintf(logfile, "%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d "
        !           852:                 ADDRX "\n", __func__, sr_base, tmp64, tmp, slb_nr, rt);
        !           853:     }
1.1       root      854: #endif
1.1.1.4 ! root      855: 
        !           856:     return rt;
        !           857: }
        !           858: 
        !           859: void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs)
        !           860: {
        !           861:     target_phys_addr_t sr_base;
        !           862:     uint64_t tmp64;
        !           863:     uint32_t tmp;
        !           864: 
        !           865:     sr_base = env->spr[SPR_ASR];
        !           866:     sr_base += 12 * slb_nr;
        !           867:     /* Copy Rs bits 37:63 to SLB 62:88 */
        !           868:     tmp = rs << 8;
        !           869:     tmp64 = (rs >> 24) & 0x7;
        !           870:     /* Copy Rs bits 33:36 to SLB 89:92 */
        !           871:     tmp |= ((rs >> 27) & 0xF) << 4;
        !           872:     /* Set the valid bit */
        !           873:     tmp64 |= 1 << 27;
        !           874:     /* Set ESID */
        !           875:     tmp64 |= (uint32_t)slb_nr << 28;
        !           876: #if defined(DEBUG_SLB)
        !           877:     if (loglevel != 0) {
        !           878:         fprintf(logfile, "%s: %d " ADDRX " => " PADDRX " %016" PRIx64
        !           879:                 " %08" PRIx32 "\n", __func__,
        !           880:                 slb_nr, rs, sr_base, tmp64, tmp);
        !           881:     }
        !           882: #endif
        !           883:     /* Write SLB entry to memory */
        !           884:     stq_phys(sr_base, tmp64);
        !           885:     stl_phys(sr_base + 8, tmp);
        !           886: }
        !           887: #endif /* defined(TARGET_PPC64) */
        !           888: 
        !           889: /* Perform segment based translation */
        !           890: static always_inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
        !           891:                                                     int sdr_sh,
        !           892:                                                     target_phys_addr_t hash,
        !           893:                                                     target_phys_addr_t mask)
        !           894: {
        !           895:     return (sdr1 & ((target_phys_addr_t)(-1ULL) << sdr_sh)) | (hash & mask);
        !           896: }
        !           897: 
        !           898: static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
        !           899:                                       target_ulong eaddr, int rw, int type)
        !           900: {
        !           901:     target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
        !           902:     target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
        !           903: #if defined(TARGET_PPC64)
        !           904:     int attr;
        !           905: #endif
        !           906:     int ds, vsid_sh, sdr_sh, pr;
        !           907:     int ret, ret2;
        !           908: 
        !           909:     pr = msr_pr;
        !           910: #if defined(TARGET_PPC64)
        !           911:     if (env->mmu_model & POWERPC_MMU_64) {
        !           912: #if defined (DEBUG_MMU)
        !           913:         if (loglevel != 0) {
        !           914:             fprintf(logfile, "Check SLBs\n");
        !           915:         }
        !           916: #endif
        !           917:         ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr);
        !           918:         if (ret < 0)
        !           919:             return ret;
        !           920:         ctx->key = ((attr & 0x40) && (pr != 0)) ||
        !           921:             ((attr & 0x80) && (pr == 0)) ? 1 : 0;
        !           922:         ds = 0;
        !           923:         ctx->nx = attr & 0x20 ? 1 : 0;
        !           924:         vsid_mask = 0x00003FFFFFFFFF80ULL;
        !           925:         vsid_sh = 7;
        !           926:         sdr_sh = 18;
        !           927:         sdr_mask = 0x3FF80;
        !           928:     } else
        !           929: #endif /* defined(TARGET_PPC64) */
        !           930:     {
        !           931:         sr = env->sr[eaddr >> 28];
        !           932:         page_mask = 0x0FFFFFFF;
        !           933:         ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
        !           934:                     ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
        !           935:         ds = sr & 0x80000000 ? 1 : 0;
        !           936:         ctx->nx = sr & 0x10000000 ? 1 : 0;
        !           937:         vsid = sr & 0x00FFFFFF;
        !           938:         vsid_mask = 0x01FFFFC0;
        !           939:         vsid_sh = 6;
        !           940:         sdr_sh = 16;
        !           941:         sdr_mask = 0xFFC0;
        !           942: #if defined (DEBUG_MMU)
        !           943:         if (loglevel != 0) {
        !           944:             fprintf(logfile, "Check segment v=" ADDRX " %d " ADDRX
        !           945:                     " nip=" ADDRX " lr=" ADDRX " ir=%d dr=%d pr=%d %d t=%d\n",
        !           946:                     eaddr, (int)(eaddr >> 28), sr, env->nip,
        !           947:                     env->lr, (int)msr_ir, (int)msr_dr, pr != 0 ? 1 : 0,
        !           948:                     rw, type);
        !           949:         }
        !           950: #endif
        !           951:     }
        !           952: #if defined (DEBUG_MMU)
        !           953:     if (loglevel != 0) {
        !           954:         fprintf(logfile, "pte segment: key=%d ds %d nx %d vsid " ADDRX "\n",
        !           955:                 ctx->key, ds, ctx->nx, vsid);
        !           956:     }
        !           957: #endif
        !           958:     ret = -1;
        !           959:     if (!ds) {
        !           960:         /* Check if instruction fetch is allowed, if needed */
        !           961:         if (type != ACCESS_CODE || ctx->nx == 0) {
        !           962:             /* Page address translation */
        !           963:             /* Primary table address */
        !           964:             sdr = env->sdr1;
        !           965:             pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;
        !           966: #if defined(TARGET_PPC64)
        !           967:             if (env->mmu_model & POWERPC_MMU_64) {
        !           968:                 htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
        !           969:                 /* XXX: this is false for 1 TB segments */
        !           970:                 hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
        !           971:             } else
        !           972: #endif
        !           973:             {
        !           974:                 htab_mask = sdr & 0x000001FF;
        !           975:                 hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
        !           976:             }
        !           977:             mask = (htab_mask << sdr_sh) | sdr_mask;
        !           978: #if defined (DEBUG_MMU)
        !           979:             if (loglevel != 0) {
        !           980:                 fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX
        !           981:                         " mask " PADDRX " " ADDRX "\n",
        !           982:                         sdr, sdr_sh, hash, mask, page_mask);
        !           983:             }
        !           984: #endif
        !           985:             ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);
        !           986:             /* Secondary table address */
        !           987:             hash = (~hash) & vsid_mask;
        !           988: #if defined (DEBUG_MMU)
        !           989:             if (loglevel != 0) {
        !           990:                 fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX
        !           991:                         " mask " PADDRX "\n",
        !           992:                         sdr, sdr_sh, hash, mask);
        !           993:             }
        !           994: #endif
        !           995:             ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
        !           996: #if defined(TARGET_PPC64)
        !           997:             if (env->mmu_model & POWERPC_MMU_64) {
        !           998:                 /* Only 5 bits of the page index are used in the AVPN */
        !           999:                 ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
        !          1000:             } else
        !          1001: #endif
        !          1002:             {
        !          1003:                 ctx->ptem = (vsid << 7) | (pgidx >> 10);
        !          1004:             }
        !          1005:             /* Initialize real address with an invalid value */
        !          1006:             ctx->raddr = (target_phys_addr_t)-1ULL;
        !          1007:             if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
        !          1008:                          env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
        !          1009:                 /* Software TLB search */
        !          1010:                 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
        !          1011:             } else {
        !          1012: #if defined (DEBUG_MMU)
        !          1013:                 if (loglevel != 0) {
        !          1014:                     fprintf(logfile, "0 sdr1=" PADDRX " vsid=" ADDRX " "
        !          1015:                             "api=" ADDRX " hash=" PADDRX
        !          1016:                             " pg_addr=" PADDRX "\n",
        !          1017:                             sdr, vsid, pgidx, hash, ctx->pg_addr[0]);
        !          1018:                 }
        !          1019: #endif
        !          1020:                 /* Primary table lookup */
        !          1021:                 ret = find_pte(env, ctx, 0, rw, type);
        !          1022:                 if (ret < 0) {
        !          1023:                     /* Secondary table lookup */
        !          1024: #if defined (DEBUG_MMU)
        !          1025:                     if (eaddr != 0xEFFFFFFF && loglevel != 0) {
        !          1026:                         fprintf(logfile, "1 sdr1=" PADDRX " vsid=" ADDRX " "
        !          1027:                                 "api=" ADDRX " hash=" PADDRX
        !          1028:                                 " pg_addr=" PADDRX "\n",
        !          1029:                                 sdr, vsid, pgidx, hash, ctx->pg_addr[1]);
        !          1030:                     }
        !          1031: #endif
        !          1032:                     ret2 = find_pte(env, ctx, 1, rw, type);
        !          1033:                     if (ret2 != -1)
        !          1034:                         ret = ret2;
        !          1035:                 }
        !          1036:             }
        !          1037: #if defined (DUMP_PAGE_TABLES)
        !          1038:             if (loglevel != 0) {
        !          1039:                 target_phys_addr_t curaddr;
        !          1040:                 uint32_t a0, a1, a2, a3;
        !          1041:                 fprintf(logfile, "Page table: " PADDRX " len " PADDRX "\n",
        !          1042:                         sdr, mask + 0x80);
        !          1043:                 for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
        !          1044:                      curaddr += 16) {
        !          1045:                     a0 = ldl_phys(curaddr);
        !          1046:                     a1 = ldl_phys(curaddr + 4);
        !          1047:                     a2 = ldl_phys(curaddr + 8);
        !          1048:                     a3 = ldl_phys(curaddr + 12);
        !          1049:                     if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
        !          1050:                         fprintf(logfile, PADDRX ": %08x %08x %08x %08x\n",
        !          1051:                                 curaddr, a0, a1, a2, a3);
        !          1052:                     }
        !          1053:                 }
        !          1054:             }
        !          1055: #endif
        !          1056:         } else {
        !          1057: #if defined (DEBUG_MMU)
        !          1058:             if (loglevel != 0)
        !          1059:                 fprintf(logfile, "No access allowed\n");
        !          1060: #endif
        !          1061:             ret = -3;
        !          1062:         }
        !          1063:     } else {
        !          1064: #if defined (DEBUG_MMU)
        !          1065:         if (loglevel != 0)
        !          1066:             fprintf(logfile, "direct store...\n");
        !          1067: #endif
        !          1068:         /* Direct-store segment : absolutely *BUGGY* for now */
        !          1069:         switch (type) {
        !          1070:         case ACCESS_INT:
        !          1071:             /* Integer load/store : only access allowed */
        !          1072:             break;
        !          1073:         case ACCESS_CODE:
        !          1074:             /* No code fetch is allowed in direct-store areas */
        !          1075:             return -4;
        !          1076:         case ACCESS_FLOAT:
1.1       root     1077:             /* Floating point load/store */
                   1078:             return -4;
                   1079:         case ACCESS_RES:
                   1080:             /* lwarx, ldarx or srwcx. */
                   1081:             return -4;
                   1082:         case ACCESS_CACHE:
                   1083:             /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
                   1084:             /* Should make the instruction do no-op.
                   1085:              * As it already do no-op, it's quite easy :-)
                   1086:              */
1.1.1.4 ! root     1087:             ctx->raddr = eaddr;
1.1       root     1088:             return 0;
                   1089:         case ACCESS_EXT:
                   1090:             /* eciwx or ecowx */
                   1091:             return -4;
                   1092:         default:
                   1093:             if (logfile) {
                   1094:                 fprintf(logfile, "ERROR: instruction should not need "
                   1095:                         "address translation\n");
                   1096:             }
                   1097:             return -4;
                   1098:         }
1.1.1.4 ! root     1099:         if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
        !          1100:             ctx->raddr = eaddr;
1.1       root     1101:             ret = 2;
                   1102:         } else {
                   1103:             ret = -2;
                   1104:         }
                   1105:     }
                   1106: 
                   1107:     return ret;
                   1108: }
                   1109: 
1.1.1.4 ! root     1110: /* Generic TLB check function for embedded PowerPC implementations */
        !          1111: static always_inline int ppcemb_tlb_check (CPUState *env, ppcemb_tlb_t *tlb,
        !          1112:                                            target_phys_addr_t *raddrp,
        !          1113:                                            target_ulong address,
        !          1114:                                            uint32_t pid, int ext, int i)
        !          1115: {
        !          1116:     target_ulong mask;
        !          1117: 
        !          1118:     /* Check valid flag */
        !          1119:     if (!(tlb->prot & PAGE_VALID)) {
        !          1120:         if (loglevel != 0)
        !          1121:             fprintf(logfile, "%s: TLB %d not valid\n", __func__, i);
        !          1122:         return -1;
        !          1123:     }
        !          1124:     mask = ~(tlb->size - 1);
        !          1125: #if defined (DEBUG_SOFTWARE_TLB)
        !          1126:     if (loglevel != 0) {
        !          1127:         fprintf(logfile, "%s: TLB %d address " ADDRX " PID %u <=> " ADDRX
        !          1128:                 " " ADDRX " %u\n",
        !          1129:                 __func__, i, address, pid, tlb->EPN, mask, (uint32_t)tlb->PID);
        !          1130:     }
        !          1131: #endif
        !          1132:     /* Check PID */
        !          1133:     if (tlb->PID != 0 && tlb->PID != pid)
        !          1134:         return -1;
        !          1135:     /* Check effective address */
        !          1136:     if ((address & mask) != tlb->EPN)
        !          1137:         return -1;
        !          1138:     *raddrp = (tlb->RPN & mask) | (address & ~mask);
        !          1139: #if (TARGET_PHYS_ADDR_BITS >= 36)
        !          1140:     if (ext) {
        !          1141:         /* Extend the physical address to 36 bits */
        !          1142:         *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
        !          1143:     }
        !          1144: #endif
        !          1145: 
        !          1146:     return 0;
        !          1147: }
        !          1148: 
        !          1149: /* Generic TLB search function for PowerPC embedded implementations */
        !          1150: int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
        !          1151: {
        !          1152:     ppcemb_tlb_t *tlb;
        !          1153:     target_phys_addr_t raddr;
        !          1154:     int i, ret;
        !          1155: 
        !          1156:     /* Default return value is no match */
        !          1157:     ret = -1;
        !          1158:     for (i = 0; i < env->nb_tlb; i++) {
        !          1159:         tlb = &env->tlb[i].tlbe;
        !          1160:         if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
        !          1161:             ret = i;
        !          1162:             break;
        !          1163:         }
        !          1164:     }
        !          1165: 
        !          1166:     return ret;
        !          1167: }
        !          1168: 
        !          1169: /* Helpers specific to PowerPC 40x implementations */
        !          1170: static always_inline void ppc4xx_tlb_invalidate_all (CPUState *env)
        !          1171: {
        !          1172:     ppcemb_tlb_t *tlb;
        !          1173:     int i;
        !          1174: 
        !          1175:     for (i = 0; i < env->nb_tlb; i++) {
        !          1176:         tlb = &env->tlb[i].tlbe;
        !          1177:         tlb->prot &= ~PAGE_VALID;
        !          1178:     }
        !          1179:     tlb_flush(env, 1);
        !          1180: }
        !          1181: 
        !          1182: static always_inline void ppc4xx_tlb_invalidate_virt (CPUState *env,
        !          1183:                                                       target_ulong eaddr,
        !          1184:                                                       uint32_t pid)
        !          1185: {
        !          1186: #if !defined(FLUSH_ALL_TLBS)
        !          1187:     ppcemb_tlb_t *tlb;
        !          1188:     target_phys_addr_t raddr;
        !          1189:     target_ulong page, end;
        !          1190:     int i;
        !          1191: 
        !          1192:     for (i = 0; i < env->nb_tlb; i++) {
        !          1193:         tlb = &env->tlb[i].tlbe;
        !          1194:         if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
        !          1195:             end = tlb->EPN + tlb->size;
        !          1196:             for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
        !          1197:                 tlb_flush_page(env, page);
        !          1198:             tlb->prot &= ~PAGE_VALID;
        !          1199:             break;
        !          1200:         }
        !          1201:     }
        !          1202: #else
        !          1203:     ppc4xx_tlb_invalidate_all(env);
        !          1204: #endif
        !          1205: }
        !          1206: 
        !          1207: int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
        !          1208:                                  target_ulong address, int rw, int access_type)
        !          1209: {
        !          1210:     ppcemb_tlb_t *tlb;
        !          1211:     target_phys_addr_t raddr;
        !          1212:     int i, ret, zsel, zpr, pr;
        !          1213: 
        !          1214:     ret = -1;
        !          1215:     raddr = (target_phys_addr_t)-1ULL;
        !          1216:     pr = msr_pr;
        !          1217:     for (i = 0; i < env->nb_tlb; i++) {
        !          1218:         tlb = &env->tlb[i].tlbe;
        !          1219:         if (ppcemb_tlb_check(env, tlb, &raddr, address,
        !          1220:                              env->spr[SPR_40x_PID], 0, i) < 0)
        !          1221:             continue;
        !          1222:         zsel = (tlb->attr >> 4) & 0xF;
        !          1223:         zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
        !          1224: #if defined (DEBUG_SOFTWARE_TLB)
        !          1225:         if (loglevel != 0) {
        !          1226:             fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
        !          1227:                     __func__, i, zsel, zpr, rw, tlb->attr);
        !          1228:         }
        !          1229: #endif
        !          1230:         /* Check execute enable bit */
        !          1231:         switch (zpr) {
        !          1232:         case 0x2:
        !          1233:             if (pr != 0)
        !          1234:                 goto check_perms;
        !          1235:             /* No break here */
        !          1236:         case 0x3:
        !          1237:             /* All accesses granted */
        !          1238:             ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
        !          1239:             ret = 0;
        !          1240:             break;
        !          1241:         case 0x0:
        !          1242:             if (pr != 0) {
        !          1243:                 ctx->prot = 0;
        !          1244:                 ret = -2;
        !          1245:                 break;
        !          1246:             }
        !          1247:             /* No break here */
        !          1248:         case 0x1:
        !          1249:         check_perms:
        !          1250:             /* Check from TLB entry */
        !          1251:             /* XXX: there is a problem here or in the TLB fill code... */
        !          1252:             ctx->prot = tlb->prot;
        !          1253:             ctx->prot |= PAGE_EXEC;
        !          1254:             ret = check_prot(ctx->prot, rw, access_type);
        !          1255:             break;
        !          1256:         }
        !          1257:         if (ret >= 0) {
        !          1258:             ctx->raddr = raddr;
        !          1259: #if defined (DEBUG_SOFTWARE_TLB)
        !          1260:             if (loglevel != 0) {
        !          1261:                 fprintf(logfile, "%s: access granted " ADDRX " => " PADDRX
        !          1262:                         " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
        !          1263:                         ret);
        !          1264:             }
        !          1265: #endif
        !          1266:             return 0;
        !          1267:         }
        !          1268:     }
        !          1269: #if defined (DEBUG_SOFTWARE_TLB)
        !          1270:     if (loglevel != 0) {
        !          1271:         fprintf(logfile, "%s: access refused " ADDRX " => " PADDRX
        !          1272:                 " %d %d\n", __func__, address, raddr, ctx->prot,
        !          1273:                 ret);
        !          1274:     }
        !          1275: #endif
        !          1276: 
        !          1277:     return ret;
        !          1278: }
        !          1279: 
        !          1280: void store_40x_sler (CPUPPCState *env, uint32_t val)
        !          1281: {
        !          1282:     /* XXX: TO BE FIXED */
        !          1283:     if (val != 0x00000000) {
        !          1284:         cpu_abort(env, "Little-endian regions are not supported by now\n");
        !          1285:     }
        !          1286:     env->spr[SPR_405_SLER] = val;
        !          1287: }
        !          1288: 
        !          1289: int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
        !          1290:                                    target_ulong address, int rw,
        !          1291:                                    int access_type)
        !          1292: {
        !          1293:     ppcemb_tlb_t *tlb;
        !          1294:     target_phys_addr_t raddr;
        !          1295:     int i, prot, ret;
        !          1296: 
        !          1297:     ret = -1;
        !          1298:     raddr = (target_phys_addr_t)-1ULL;
        !          1299:     for (i = 0; i < env->nb_tlb; i++) {
        !          1300:         tlb = &env->tlb[i].tlbe;
        !          1301:         if (ppcemb_tlb_check(env, tlb, &raddr, address,
        !          1302:                              env->spr[SPR_BOOKE_PID], 1, i) < 0)
        !          1303:             continue;
        !          1304:         if (msr_pr != 0)
        !          1305:             prot = tlb->prot & 0xF;
        !          1306:         else
        !          1307:             prot = (tlb->prot >> 4) & 0xF;
        !          1308:         /* Check the address space */
        !          1309:         if (access_type == ACCESS_CODE) {
        !          1310:             if (msr_ir != (tlb->attr & 1))
        !          1311:                 continue;
        !          1312:             ctx->prot = prot;
        !          1313:             if (prot & PAGE_EXEC) {
        !          1314:                 ret = 0;
        !          1315:                 break;
        !          1316:             }
        !          1317:             ret = -3;
        !          1318:         } else {
        !          1319:             if (msr_dr != (tlb->attr & 1))
        !          1320:                 continue;
        !          1321:             ctx->prot = prot;
        !          1322:             if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
        !          1323:                 ret = 0;
        !          1324:                 break;
        !          1325:             }
        !          1326:             ret = -2;
        !          1327:         }
        !          1328:     }
        !          1329:     if (ret >= 0)
        !          1330:         ctx->raddr = raddr;
        !          1331: 
        !          1332:     return ret;
        !          1333: }
        !          1334: 
        !          1335: static always_inline int check_physical (CPUState *env, mmu_ctx_t *ctx,
        !          1336:                                          target_ulong eaddr, int rw)
        !          1337: {
        !          1338:     int in_plb, ret;
        !          1339: 
        !          1340:     ctx->raddr = eaddr;
        !          1341:     ctx->prot = PAGE_READ | PAGE_EXEC;
        !          1342:     ret = 0;
        !          1343:     switch (env->mmu_model) {
        !          1344:     case POWERPC_MMU_32B:
        !          1345:     case POWERPC_MMU_601:
        !          1346:     case POWERPC_MMU_SOFT_6xx:
        !          1347:     case POWERPC_MMU_SOFT_74xx:
        !          1348:     case POWERPC_MMU_SOFT_4xx:
        !          1349:     case POWERPC_MMU_REAL:
        !          1350:     case POWERPC_MMU_BOOKE:
        !          1351:         ctx->prot |= PAGE_WRITE;
        !          1352:         break;
        !          1353: #if defined(TARGET_PPC64)
        !          1354:     case POWERPC_MMU_620:
        !          1355:     case POWERPC_MMU_64B:
        !          1356:         /* Real address are 60 bits long */
        !          1357:         ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
        !          1358:         ctx->prot |= PAGE_WRITE;
        !          1359:         break;
        !          1360: #endif
        !          1361:     case POWERPC_MMU_SOFT_4xx_Z:
        !          1362:         if (unlikely(msr_pe != 0)) {
        !          1363:             /* 403 family add some particular protections,
        !          1364:              * using PBL/PBU registers for accesses with no translation.
        !          1365:              */
        !          1366:             in_plb =
        !          1367:                 /* Check PLB validity */
        !          1368:                 (env->pb[0] < env->pb[1] &&
        !          1369:                  /* and address in plb area */
        !          1370:                  eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
        !          1371:                 (env->pb[2] < env->pb[3] &&
        !          1372:                  eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
        !          1373:             if (in_plb ^ msr_px) {
        !          1374:                 /* Access in protected area */
        !          1375:                 if (rw == 1) {
        !          1376:                     /* Access is not allowed */
        !          1377:                     ret = -2;
        !          1378:                 }
        !          1379:             } else {
        !          1380:                 /* Read-write access is allowed */
        !          1381:                 ctx->prot |= PAGE_WRITE;
        !          1382:             }
        !          1383:         }
        !          1384:         break;
        !          1385:     case POWERPC_MMU_MPC8xx:
        !          1386:         /* XXX: TODO */
        !          1387:         cpu_abort(env, "MPC8xx MMU model is not implemented\n");
        !          1388:         break;
        !          1389:     case POWERPC_MMU_BOOKE_FSL:
        !          1390:         /* XXX: TODO */
        !          1391:         cpu_abort(env, "BookE FSL MMU model not implemented\n");
        !          1392:         break;
        !          1393:     default:
        !          1394:         cpu_abort(env, "Unknown or invalid MMU model\n");
        !          1395:         return -1;
        !          1396:     }
        !          1397: 
        !          1398:     return ret;
        !          1399: }
        !          1400: 
        !          1401: int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
        !          1402:                           int rw, int access_type)
1.1       root     1403: {
                   1404:     int ret;
1.1.1.4 ! root     1405: 
1.1       root     1406: #if 0
1.1.1.4 ! root     1407:     if (loglevel != 0) {
1.1       root     1408:         fprintf(logfile, "%s\n", __func__);
                   1409:     }
1.1.1.4 ! root     1410: #endif
1.1       root     1411:     if ((access_type == ACCESS_CODE && msr_ir == 0) ||
                   1412:         (access_type != ACCESS_CODE && msr_dr == 0)) {
                   1413:         /* No address translation */
1.1.1.4 ! root     1414:         ret = check_physical(env, ctx, eaddr, rw);
1.1       root     1415:     } else {
1.1.1.4 ! root     1416:         ret = -1;
        !          1417:         switch (env->mmu_model) {
        !          1418:         case POWERPC_MMU_32B:
        !          1419:         case POWERPC_MMU_601:
        !          1420:         case POWERPC_MMU_SOFT_6xx:
        !          1421:         case POWERPC_MMU_SOFT_74xx:
        !          1422: #if defined(TARGET_PPC64)
        !          1423:         case POWERPC_MMU_620:
        !          1424:         case POWERPC_MMU_64B:
        !          1425: #endif
        !          1426:             /* Try to find a BAT */
        !          1427:             if (env->nb_BATs != 0)
        !          1428:                 ret = get_bat(env, ctx, eaddr, rw, access_type);
        !          1429:             if (ret < 0) {
        !          1430:                 /* We didn't match any BAT entry or don't have BATs */
        !          1431:                 ret = get_segment(env, ctx, eaddr, rw, access_type);
        !          1432:             }
        !          1433:             break;
        !          1434:         case POWERPC_MMU_SOFT_4xx:
        !          1435:         case POWERPC_MMU_SOFT_4xx_Z:
        !          1436:             ret = mmu40x_get_physical_address(env, ctx, eaddr,
        !          1437:                                               rw, access_type);
        !          1438:             break;
        !          1439:         case POWERPC_MMU_BOOKE:
        !          1440:             ret = mmubooke_get_physical_address(env, ctx, eaddr,
        !          1441:                                                 rw, access_type);
        !          1442:             break;
        !          1443:         case POWERPC_MMU_MPC8xx:
        !          1444:             /* XXX: TODO */
        !          1445:             cpu_abort(env, "MPC8xx MMU model is not implemented\n");
        !          1446:             break;
        !          1447:         case POWERPC_MMU_BOOKE_FSL:
        !          1448:             /* XXX: TODO */
        !          1449:             cpu_abort(env, "BookE FSL MMU model not implemented\n");
        !          1450:             return -1;
        !          1451:         case POWERPC_MMU_REAL:
        !          1452:             cpu_abort(env, "PowerPC in real mode do not do any translation\n");
        !          1453:             return -1;
        !          1454:         default:
        !          1455:             cpu_abort(env, "Unknown or invalid MMU model\n");
        !          1456:             return -1;
1.1       root     1457:         }
                   1458:     }
                   1459: #if 0
1.1.1.4 ! root     1460:     if (loglevel != 0) {
        !          1461:         fprintf(logfile, "%s address " ADDRX " => %d " PADDRX "\n",
        !          1462:                 __func__, eaddr, ret, ctx->raddr);
1.1       root     1463:     }
1.1.1.4 ! root     1464: #endif
        !          1465: 
1.1       root     1466:     return ret;
                   1467: }
                   1468: 
1.1.1.4 ! root     1469: target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1.1       root     1470: {
1.1.1.4 ! root     1471:     mmu_ctx_t ctx;
1.1       root     1472: 
1.1.1.4 ! root     1473:     if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1.1       root     1474:         return -1;
1.1.1.4 ! root     1475: 
        !          1476:     return ctx.raddr & TARGET_PAGE_MASK;
1.1       root     1477: }
                   1478: 
                   1479: /* Perform address translation */
1.1.1.4 ! root     1480: int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
        !          1481:                               int mmu_idx, int is_softmmu)
1.1       root     1482: {
1.1.1.4 ! root     1483:     mmu_ctx_t ctx;
1.1       root     1484:     int access_type;
                   1485:     int ret = 0;
                   1486: 
                   1487:     if (rw == 2) {
                   1488:         /* code access */
                   1489:         rw = 0;
                   1490:         access_type = ACCESS_CODE;
                   1491:     } else {
                   1492:         /* data access */
                   1493:         /* XXX: put correct access by using cpu_restore_state()
                   1494:            correctly */
                   1495:         access_type = ACCESS_INT;
                   1496:         //        access_type = env->access_type;
                   1497:     }
1.1.1.4 ! root     1498:     ret = get_physical_address(env, &ctx, address, rw, access_type);
1.1       root     1499:     if (ret == 0) {
1.1.1.4 ! root     1500:         ret = tlb_set_page_exec(env, address & TARGET_PAGE_MASK,
        !          1501:                                 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
        !          1502:                                 mmu_idx, is_softmmu);
1.1       root     1503:     } else if (ret < 0) {
                   1504: #if defined (DEBUG_MMU)
1.1.1.4 ! root     1505:         if (loglevel != 0)
        !          1506:             cpu_dump_state(env, logfile, fprintf, 0);
1.1       root     1507: #endif
                   1508:         if (access_type == ACCESS_CODE) {
                   1509:             switch (ret) {
                   1510:             case -1:
1.1.1.4 ! root     1511:                 /* No matches in page tables or TLB */
        !          1512:                 switch (env->mmu_model) {
        !          1513:                 case POWERPC_MMU_SOFT_6xx:
        !          1514:                     env->exception_index = POWERPC_EXCP_IFTLB;
        !          1515:                     env->error_code = 1 << 18;
        !          1516:                     env->spr[SPR_IMISS] = address;
        !          1517:                     env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
        !          1518:                     goto tlb_miss;
        !          1519:                 case POWERPC_MMU_SOFT_74xx:
        !          1520:                     env->exception_index = POWERPC_EXCP_IFTLB;
        !          1521:                     goto tlb_miss_74xx;
        !          1522:                 case POWERPC_MMU_SOFT_4xx:
        !          1523:                 case POWERPC_MMU_SOFT_4xx_Z:
        !          1524:                     env->exception_index = POWERPC_EXCP_ITLB;
        !          1525:                     env->error_code = 0;
        !          1526:                     env->spr[SPR_40x_DEAR] = address;
        !          1527:                     env->spr[SPR_40x_ESR] = 0x00000000;
        !          1528:                     break;
        !          1529:                 case POWERPC_MMU_32B:
        !          1530:                 case POWERPC_MMU_601:
        !          1531: #if defined(TARGET_PPC64)
        !          1532:                 case POWERPC_MMU_620:
        !          1533:                 case POWERPC_MMU_64B:
        !          1534: #endif
        !          1535:                     env->exception_index = POWERPC_EXCP_ISI;
        !          1536:                     env->error_code = 0x40000000;
        !          1537:                     break;
        !          1538:                 case POWERPC_MMU_BOOKE:
        !          1539:                     /* XXX: TODO */
        !          1540:                     cpu_abort(env, "BookE MMU model is not implemented\n");
        !          1541:                     return -1;
        !          1542:                 case POWERPC_MMU_BOOKE_FSL:
        !          1543:                     /* XXX: TODO */
        !          1544:                     cpu_abort(env, "BookE FSL MMU model is not implemented\n");
        !          1545:                     return -1;
        !          1546:                 case POWERPC_MMU_MPC8xx:
        !          1547:                     /* XXX: TODO */
        !          1548:                     cpu_abort(env, "MPC8xx MMU model is not implemented\n");
        !          1549:                     break;
        !          1550:                 case POWERPC_MMU_REAL:
        !          1551:                     cpu_abort(env, "PowerPC in real mode should never raise "
        !          1552:                               "any MMU exceptions\n");
        !          1553:                     return -1;
        !          1554:                 default:
        !          1555:                     cpu_abort(env, "Unknown or invalid MMU model\n");
        !          1556:                     return -1;
        !          1557:                 }
1.1       root     1558:                 break;
                   1559:             case -2:
                   1560:                 /* Access rights violation */
1.1.1.4 ! root     1561:                 env->exception_index = POWERPC_EXCP_ISI;
        !          1562:                 env->error_code = 0x08000000;
1.1       root     1563:                 break;
                   1564:             case -3:
1.1.1.4 ! root     1565:                 /* No execute protection violation */
        !          1566:                 env->exception_index = POWERPC_EXCP_ISI;
        !          1567:                 env->error_code = 0x10000000;
1.1       root     1568:                 break;
                   1569:             case -4:
                   1570:                 /* Direct store exception */
                   1571:                 /* No code fetch is allowed in direct-store areas */
1.1.1.4 ! root     1572:                 env->exception_index = POWERPC_EXCP_ISI;
        !          1573:                 env->error_code = 0x10000000;
1.1       root     1574:                 break;
1.1.1.4 ! root     1575: #if defined(TARGET_PPC64)
1.1       root     1576:             case -5:
                   1577:                 /* No match in segment table */
1.1.1.4 ! root     1578:                 if (env->mmu_model == POWERPC_MMU_620) {
        !          1579:                     env->exception_index = POWERPC_EXCP_ISI;
        !          1580:                     /* XXX: this might be incorrect */
        !          1581:                     env->error_code = 0x40000000;
        !          1582:                 } else {
        !          1583:                     env->exception_index = POWERPC_EXCP_ISEG;
        !          1584:                     env->error_code = 0;
        !          1585:                 }
1.1       root     1586:                 break;
1.1.1.4 ! root     1587: #endif
1.1       root     1588:             }
                   1589:         } else {
                   1590:             switch (ret) {
                   1591:             case -1:
1.1.1.4 ! root     1592:                 /* No matches in page tables or TLB */
        !          1593:                 switch (env->mmu_model) {
        !          1594:                 case POWERPC_MMU_SOFT_6xx:
        !          1595:                     if (rw == 1) {
        !          1596:                         env->exception_index = POWERPC_EXCP_DSTLB;
        !          1597:                         env->error_code = 1 << 16;
        !          1598:                     } else {
        !          1599:                         env->exception_index = POWERPC_EXCP_DLTLB;
        !          1600:                         env->error_code = 0;
        !          1601:                     }
        !          1602:                     env->spr[SPR_DMISS] = address;
        !          1603:                     env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
        !          1604:                 tlb_miss:
        !          1605:                     env->error_code |= ctx.key << 19;
        !          1606:                     env->spr[SPR_HASH1] = ctx.pg_addr[0];
        !          1607:                     env->spr[SPR_HASH2] = ctx.pg_addr[1];
        !          1608:                     break;
        !          1609:                 case POWERPC_MMU_SOFT_74xx:
        !          1610:                     if (rw == 1) {
        !          1611:                         env->exception_index = POWERPC_EXCP_DSTLB;
        !          1612:                     } else {
        !          1613:                         env->exception_index = POWERPC_EXCP_DLTLB;
        !          1614:                     }
        !          1615:                 tlb_miss_74xx:
        !          1616:                     /* Implement LRU algorithm */
        !          1617:                     env->error_code = ctx.key << 19;
        !          1618:                     env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
        !          1619:                         ((env->last_way + 1) & (env->nb_ways - 1));
        !          1620:                     env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
        !          1621:                     break;
        !          1622:                 case POWERPC_MMU_SOFT_4xx:
        !          1623:                 case POWERPC_MMU_SOFT_4xx_Z:
        !          1624:                     env->exception_index = POWERPC_EXCP_DTLB;
        !          1625:                     env->error_code = 0;
        !          1626:                     env->spr[SPR_40x_DEAR] = address;
        !          1627:                     if (rw)
        !          1628:                         env->spr[SPR_40x_ESR] = 0x00800000;
        !          1629:                     else
        !          1630:                         env->spr[SPR_40x_ESR] = 0x00000000;
        !          1631:                     break;
        !          1632:                 case POWERPC_MMU_32B:
        !          1633:                 case POWERPC_MMU_601:
        !          1634: #if defined(TARGET_PPC64)
        !          1635:                 case POWERPC_MMU_620:
        !          1636:                 case POWERPC_MMU_64B:
        !          1637: #endif
        !          1638:                     env->exception_index = POWERPC_EXCP_DSI;
        !          1639:                     env->error_code = 0;
        !          1640:                     env->spr[SPR_DAR] = address;
        !          1641:                     if (rw == 1)
        !          1642:                         env->spr[SPR_DSISR] = 0x42000000;
        !          1643:                     else
        !          1644:                         env->spr[SPR_DSISR] = 0x40000000;
        !          1645:                     break;
        !          1646:                 case POWERPC_MMU_MPC8xx:
        !          1647:                     /* XXX: TODO */
        !          1648:                     cpu_abort(env, "MPC8xx MMU model is not implemented\n");
        !          1649:                     break;
        !          1650:                 case POWERPC_MMU_BOOKE:
        !          1651:                     /* XXX: TODO */
        !          1652:                     cpu_abort(env, "BookE MMU model is not implemented\n");
        !          1653:                     return -1;
        !          1654:                 case POWERPC_MMU_BOOKE_FSL:
        !          1655:                     /* XXX: TODO */
        !          1656:                     cpu_abort(env, "BookE FSL MMU model is not implemented\n");
        !          1657:                     return -1;
        !          1658:                 case POWERPC_MMU_REAL:
        !          1659:                     cpu_abort(env, "PowerPC in real mode should never raise "
        !          1660:                               "any MMU exceptions\n");
        !          1661:                     return -1;
        !          1662:                 default:
        !          1663:                     cpu_abort(env, "Unknown or invalid MMU model\n");
        !          1664:                     return -1;
        !          1665:                 }
1.1       root     1666:                 break;
                   1667:             case -2:
                   1668:                 /* Access rights violation */
1.1.1.4 ! root     1669:                 env->exception_index = POWERPC_EXCP_DSI;
        !          1670:                 env->error_code = 0;
        !          1671:                 env->spr[SPR_DAR] = address;
        !          1672:                 if (rw == 1)
        !          1673:                     env->spr[SPR_DSISR] = 0x0A000000;
        !          1674:                 else
        !          1675:                     env->spr[SPR_DSISR] = 0x08000000;
1.1       root     1676:                 break;
                   1677:             case -4:
                   1678:                 /* Direct store exception */
                   1679:                 switch (access_type) {
                   1680:                 case ACCESS_FLOAT:
                   1681:                     /* Floating point load/store */
1.1.1.4 ! root     1682:                     env->exception_index = POWERPC_EXCP_ALIGN;
        !          1683:                     env->error_code = POWERPC_EXCP_ALIGN_FP;
        !          1684:                     env->spr[SPR_DAR] = address;
1.1       root     1685:                     break;
                   1686:                 case ACCESS_RES:
1.1.1.4 ! root     1687:                     /* lwarx, ldarx or stwcx. */
        !          1688:                     env->exception_index = POWERPC_EXCP_DSI;
        !          1689:                     env->error_code = 0;
        !          1690:                     env->spr[SPR_DAR] = address;
        !          1691:                     if (rw == 1)
        !          1692:                         env->spr[SPR_DSISR] = 0x06000000;
        !          1693:                     else
        !          1694:                         env->spr[SPR_DSISR] = 0x04000000;
1.1       root     1695:                     break;
                   1696:                 case ACCESS_EXT:
                   1697:                     /* eciwx or ecowx */
1.1.1.4 ! root     1698:                     env->exception_index = POWERPC_EXCP_DSI;
        !          1699:                     env->error_code = 0;
        !          1700:                     env->spr[SPR_DAR] = address;
        !          1701:                     if (rw == 1)
        !          1702:                         env->spr[SPR_DSISR] = 0x06100000;
        !          1703:                     else
        !          1704:                         env->spr[SPR_DSISR] = 0x04100000;
1.1       root     1705:                     break;
                   1706:                 default:
1.1.1.4 ! root     1707:                     printf("DSI: invalid exception (%d)\n", ret);
        !          1708:                     env->exception_index = POWERPC_EXCP_PROGRAM;
        !          1709:                     env->error_code =
        !          1710:                         POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
        !          1711:                     env->spr[SPR_DAR] = address;
1.1       root     1712:                     break;
                   1713:                 }
                   1714:                 break;
1.1.1.4 ! root     1715: #if defined(TARGET_PPC64)
1.1       root     1716:             case -5:
                   1717:                 /* No match in segment table */
1.1.1.4 ! root     1718:                 if (env->mmu_model == POWERPC_MMU_620) {
        !          1719:                     env->exception_index = POWERPC_EXCP_DSI;
        !          1720:                     env->error_code = 0;
        !          1721:                     env->spr[SPR_DAR] = address;
        !          1722:                     /* XXX: this might be incorrect */
        !          1723:                     if (rw == 1)
        !          1724:                         env->spr[SPR_DSISR] = 0x42000000;
        !          1725:                     else
        !          1726:                         env->spr[SPR_DSISR] = 0x40000000;
        !          1727:                 } else {
        !          1728:                     env->exception_index = POWERPC_EXCP_DSEG;
        !          1729:                     env->error_code = 0;
        !          1730:                     env->spr[SPR_DAR] = address;
        !          1731:                 }
1.1       root     1732:                 break;
1.1.1.4 ! root     1733: #endif
1.1       root     1734:             }
                   1735:         }
                   1736: #if 0
1.1.1.4 ! root     1737:         printf("%s: set exception to %d %02x\n", __func__,
        !          1738:                env->exception, env->error_code);
1.1       root     1739: #endif
                   1740:         ret = 1;
                   1741:     }
1.1.1.4 ! root     1742: 
1.1       root     1743:     return ret;
                   1744: }
                   1745: 
                   1746: /*****************************************************************************/
                   1747: /* BATs management */
                   1748: #if !defined(FLUSH_ALL_TLBS)
1.1.1.4 ! root     1749: static always_inline void do_invalidate_BAT (CPUPPCState *env,
        !          1750:                                              target_ulong BATu,
        !          1751:                                              target_ulong mask)
1.1       root     1752: {
                   1753:     target_ulong base, end, page;
1.1.1.4 ! root     1754: 
1.1       root     1755:     base = BATu & ~0x0001FFFF;
                   1756:     end = base + mask + 0x00020000;
                   1757: #if defined (DEBUG_BATS)
1.1.1.4 ! root     1758:     if (loglevel != 0) {
        !          1759:         fprintf(logfile, "Flush BAT from " ADDRX " to " ADDRX " (" ADDRX ")\n",
        !          1760:                 base, end, mask);
        !          1761:     }
1.1       root     1762: #endif
                   1763:     for (page = base; page != end; page += TARGET_PAGE_SIZE)
                   1764:         tlb_flush_page(env, page);
                   1765: #if defined (DEBUG_BATS)
                   1766:     if (loglevel != 0)
                   1767:         fprintf(logfile, "Flush done\n");
                   1768: #endif
                   1769: }
                   1770: #endif
                   1771: 
1.1.1.4 ! root     1772: static always_inline void dump_store_bat (CPUPPCState *env, char ID,
        !          1773:                                           int ul, int nr, target_ulong value)
1.1       root     1774: {
                   1775: #if defined (DEBUG_BATS)
                   1776:     if (loglevel != 0) {
1.1.1.4 ! root     1777:         fprintf(logfile, "Set %cBAT%d%c to " ADDRX " (" ADDRX ")\n",
        !          1778:                 ID, nr, ul == 0 ? 'u' : 'l', value, env->nip);
1.1       root     1779:     }
                   1780: #endif
                   1781: }
                   1782: 
                   1783: target_ulong do_load_ibatu (CPUPPCState *env, int nr)
                   1784: {
                   1785:     return env->IBAT[0][nr];
                   1786: }
                   1787: 
                   1788: target_ulong do_load_ibatl (CPUPPCState *env, int nr)
                   1789: {
                   1790:     return env->IBAT[1][nr];
                   1791: }
                   1792: 
                   1793: void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
                   1794: {
                   1795:     target_ulong mask;
                   1796: 
                   1797:     dump_store_bat(env, 'I', 0, nr, value);
                   1798:     if (env->IBAT[0][nr] != value) {
                   1799:         mask = (value << 15) & 0x0FFE0000UL;
                   1800: #if !defined(FLUSH_ALL_TLBS)
                   1801:         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
                   1802: #endif
                   1803:         /* When storing valid upper BAT, mask BEPI and BRPN
                   1804:          * and invalidate all TLBs covered by this BAT
                   1805:          */
                   1806:         mask = (value << 15) & 0x0FFE0000UL;
                   1807:         env->IBAT[0][nr] = (value & 0x00001FFFUL) |
                   1808:             (value & ~0x0001FFFFUL & ~mask);
                   1809:         env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
                   1810:             (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
                   1811: #if !defined(FLUSH_ALL_TLBS)
                   1812:         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1.1.1.4 ! root     1813: #else
1.1       root     1814:         tlb_flush(env, 1);
                   1815: #endif
                   1816:     }
                   1817: }
                   1818: 
                   1819: void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
                   1820: {
                   1821:     dump_store_bat(env, 'I', 1, nr, value);
                   1822:     env->IBAT[1][nr] = value;
                   1823: }
                   1824: 
                   1825: target_ulong do_load_dbatu (CPUPPCState *env, int nr)
                   1826: {
                   1827:     return env->DBAT[0][nr];
                   1828: }
                   1829: 
                   1830: target_ulong do_load_dbatl (CPUPPCState *env, int nr)
                   1831: {
                   1832:     return env->DBAT[1][nr];
                   1833: }
                   1834: 
                   1835: void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
                   1836: {
                   1837:     target_ulong mask;
                   1838: 
                   1839:     dump_store_bat(env, 'D', 0, nr, value);
                   1840:     if (env->DBAT[0][nr] != value) {
                   1841:         /* When storing valid upper BAT, mask BEPI and BRPN
                   1842:          * and invalidate all TLBs covered by this BAT
                   1843:          */
                   1844:         mask = (value << 15) & 0x0FFE0000UL;
                   1845: #if !defined(FLUSH_ALL_TLBS)
                   1846:         do_invalidate_BAT(env, env->DBAT[0][nr], mask);
                   1847: #endif
                   1848:         mask = (value << 15) & 0x0FFE0000UL;
                   1849:         env->DBAT[0][nr] = (value & 0x00001FFFUL) |
                   1850:             (value & ~0x0001FFFFUL & ~mask);
                   1851:         env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
                   1852:             (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
                   1853: #if !defined(FLUSH_ALL_TLBS)
                   1854:         do_invalidate_BAT(env, env->DBAT[0][nr], mask);
                   1855: #else
                   1856:         tlb_flush(env, 1);
                   1857: #endif
                   1858:     }
                   1859: }
                   1860: 
                   1861: void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
                   1862: {
                   1863:     dump_store_bat(env, 'D', 1, nr, value);
                   1864:     env->DBAT[1][nr] = value;
                   1865: }
                   1866: 
1.1.1.4 ! root     1867: void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1.1       root     1868: {
1.1.1.4 ! root     1869:     target_ulong mask;
        !          1870:     int do_inval;
1.1       root     1871: 
1.1.1.4 ! root     1872:     dump_store_bat(env, 'I', 0, nr, value);
        !          1873:     if (env->IBAT[0][nr] != value) {
        !          1874:         do_inval = 0;
        !          1875:         mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
        !          1876:         if (env->IBAT[1][nr] & 0x40) {
        !          1877:             /* Invalidate BAT only if it is valid */
        !          1878: #if !defined(FLUSH_ALL_TLBS)
        !          1879:             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
        !          1880: #else
        !          1881:             do_inval = 1;
        !          1882: #endif
        !          1883:         }
        !          1884:         /* When storing valid upper BAT, mask BEPI and BRPN
        !          1885:          * and invalidate all TLBs covered by this BAT
        !          1886:          */
        !          1887:         env->IBAT[0][nr] = (value & 0x00001FFFUL) |
        !          1888:             (value & ~0x0001FFFFUL & ~mask);
        !          1889:         env->DBAT[0][nr] = env->IBAT[0][nr];
        !          1890:         if (env->IBAT[1][nr] & 0x40) {
        !          1891: #if !defined(FLUSH_ALL_TLBS)
        !          1892:             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
        !          1893: #else
        !          1894:             do_inval = 1;
        !          1895: #endif
        !          1896:         }
        !          1897: #if defined(FLUSH_ALL_TLBS)
        !          1898:         if (do_inval)
        !          1899:             tlb_flush(env, 1);
        !          1900: #endif
        !          1901:     }
1.1       root     1902: }
                   1903: 
1.1.1.4 ! root     1904: void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1.1       root     1905: {
1.1.1.4 ! root     1906:     target_ulong mask;
        !          1907:     int do_inval;
1.1       root     1908: 
1.1.1.4 ! root     1909:     dump_store_bat(env, 'I', 1, nr, value);
        !          1910:     if (env->IBAT[1][nr] != value) {
        !          1911:         do_inval = 0;
        !          1912:         if (env->IBAT[1][nr] & 0x40) {
        !          1913: #if !defined(FLUSH_ALL_TLBS)
        !          1914:             mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
        !          1915:             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
        !          1916: #else
        !          1917:             do_inval = 1;
        !          1918: #endif
        !          1919:         }
        !          1920:         if (value & 0x40) {
        !          1921: #if !defined(FLUSH_ALL_TLBS)
        !          1922:             mask = (value << 17) & 0x0FFE0000UL;
        !          1923:             do_invalidate_BAT(env, env->IBAT[0][nr], mask);
        !          1924: #else
        !          1925:             do_inval = 1;
        !          1926: #endif
        !          1927:         }
        !          1928:         env->IBAT[1][nr] = value;
        !          1929:         env->DBAT[1][nr] = value;
        !          1930: #if defined(FLUSH_ALL_TLBS)
        !          1931:         if (do_inval)
        !          1932:             tlb_flush(env, 1);
        !          1933: #endif
        !          1934:     }
        !          1935: }
        !          1936: 
        !          1937: /*****************************************************************************/
        !          1938: /* TLB management */
        !          1939: void ppc_tlb_invalidate_all (CPUPPCState *env)
        !          1940: {
        !          1941:     switch (env->mmu_model) {
        !          1942:     case POWERPC_MMU_SOFT_6xx:
        !          1943:     case POWERPC_MMU_SOFT_74xx:
        !          1944:         ppc6xx_tlb_invalidate_all(env);
        !          1945:         break;
        !          1946:     case POWERPC_MMU_SOFT_4xx:
        !          1947:     case POWERPC_MMU_SOFT_4xx_Z:
        !          1948:         ppc4xx_tlb_invalidate_all(env);
        !          1949:         break;
        !          1950:     case POWERPC_MMU_REAL:
        !          1951:         cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
        !          1952:         break;
        !          1953:     case POWERPC_MMU_MPC8xx:
        !          1954:         /* XXX: TODO */
        !          1955:         cpu_abort(env, "MPC8xx MMU model is not implemented\n");
        !          1956:         break;
        !          1957:     case POWERPC_MMU_BOOKE:
        !          1958:         /* XXX: TODO */
        !          1959:         cpu_abort(env, "BookE MMU model is not implemented\n");
        !          1960:         break;
        !          1961:     case POWERPC_MMU_BOOKE_FSL:
        !          1962:         /* XXX: TODO */
        !          1963:         cpu_abort(env, "BookE MMU model is not implemented\n");
        !          1964:         break;
        !          1965:     case POWERPC_MMU_32B:
        !          1966:     case POWERPC_MMU_601:
        !          1967: #if defined(TARGET_PPC64)
        !          1968:     case POWERPC_MMU_620:
        !          1969:     case POWERPC_MMU_64B:
        !          1970: #endif /* defined(TARGET_PPC64) */
        !          1971:         tlb_flush(env, 1);
        !          1972:         break;
        !          1973:     default:
        !          1974:         /* XXX: TODO */
        !          1975:         cpu_abort(env, "Unknown MMU model\n");
        !          1976:         break;
        !          1977:     }
        !          1978: }
        !          1979: 
        !          1980: void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
        !          1981: {
        !          1982: #if !defined(FLUSH_ALL_TLBS)
        !          1983:     addr &= TARGET_PAGE_MASK;
        !          1984:     switch (env->mmu_model) {
        !          1985:     case POWERPC_MMU_SOFT_6xx:
        !          1986:     case POWERPC_MMU_SOFT_74xx:
        !          1987:         ppc6xx_tlb_invalidate_virt(env, addr, 0);
        !          1988:         if (env->id_tlbs == 1)
        !          1989:             ppc6xx_tlb_invalidate_virt(env, addr, 1);
        !          1990:         break;
        !          1991:     case POWERPC_MMU_SOFT_4xx:
        !          1992:     case POWERPC_MMU_SOFT_4xx_Z:
        !          1993:         ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
        !          1994:         break;
        !          1995:     case POWERPC_MMU_REAL:
        !          1996:         cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
        !          1997:         break;
        !          1998:     case POWERPC_MMU_MPC8xx:
        !          1999:         /* XXX: TODO */
        !          2000:         cpu_abort(env, "MPC8xx MMU model is not implemented\n");
        !          2001:         break;
        !          2002:     case POWERPC_MMU_BOOKE:
        !          2003:         /* XXX: TODO */
        !          2004:         cpu_abort(env, "BookE MMU model is not implemented\n");
        !          2005:         break;
        !          2006:     case POWERPC_MMU_BOOKE_FSL:
        !          2007:         /* XXX: TODO */
        !          2008:         cpu_abort(env, "BookE FSL MMU model is not implemented\n");
        !          2009:         break;
        !          2010:     case POWERPC_MMU_32B:
        !          2011:     case POWERPC_MMU_601:
        !          2012:         /* tlbie invalidate TLBs for all segments */
        !          2013:         addr &= ~((target_ulong)-1ULL << 28);
        !          2014:         /* XXX: this case should be optimized,
        !          2015:          * giving a mask to tlb_flush_page
        !          2016:          */
        !          2017:         tlb_flush_page(env, addr | (0x0 << 28));
        !          2018:         tlb_flush_page(env, addr | (0x1 << 28));
        !          2019:         tlb_flush_page(env, addr | (0x2 << 28));
        !          2020:         tlb_flush_page(env, addr | (0x3 << 28));
        !          2021:         tlb_flush_page(env, addr | (0x4 << 28));
        !          2022:         tlb_flush_page(env, addr | (0x5 << 28));
        !          2023:         tlb_flush_page(env, addr | (0x6 << 28));
        !          2024:         tlb_flush_page(env, addr | (0x7 << 28));
        !          2025:         tlb_flush_page(env, addr | (0x8 << 28));
        !          2026:         tlb_flush_page(env, addr | (0x9 << 28));
        !          2027:         tlb_flush_page(env, addr | (0xA << 28));
        !          2028:         tlb_flush_page(env, addr | (0xB << 28));
        !          2029:         tlb_flush_page(env, addr | (0xC << 28));
        !          2030:         tlb_flush_page(env, addr | (0xD << 28));
        !          2031:         tlb_flush_page(env, addr | (0xE << 28));
        !          2032:         tlb_flush_page(env, addr | (0xF << 28));
        !          2033:         break;
        !          2034: #if defined(TARGET_PPC64)
        !          2035:     case POWERPC_MMU_620:
        !          2036:     case POWERPC_MMU_64B:
        !          2037:         /* tlbie invalidate TLBs for all segments */
        !          2038:         /* XXX: given the fact that there are too many segments to invalidate,
        !          2039:          *      and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
        !          2040:          *      we just invalidate all TLBs
        !          2041:          */
        !          2042:         tlb_flush(env, 1);
        !          2043:         break;
        !          2044: #endif /* defined(TARGET_PPC64) */
        !          2045:     default:
        !          2046:         /* XXX: TODO */
        !          2047:         cpu_abort(env, "Unknown MMU model\n");
        !          2048:         break;
        !          2049:     }
        !          2050: #else
        !          2051:     ppc_tlb_invalidate_all(env);
        !          2052: #endif
        !          2053: }
        !          2054: 
        !          2055: /*****************************************************************************/
        !          2056: /* Special registers manipulation */
        !          2057: #if defined(TARGET_PPC64)
        !          2058: target_ulong ppc_load_asr (CPUPPCState *env)
        !          2059: {
        !          2060:     return env->asr;
        !          2061: }
        !          2062: 
        !          2063: void ppc_store_asr (CPUPPCState *env, target_ulong value)
        !          2064: {
        !          2065:     if (env->asr != value) {
        !          2066:         env->asr = value;
        !          2067:         tlb_flush(env, 1);
        !          2068:     }
        !          2069: }
        !          2070: #endif
        !          2071: 
        !          2072: target_ulong do_load_sdr1 (CPUPPCState *env)
        !          2073: {
        !          2074:     return env->sdr1;
1.1       root     2075: }
                   2076: 
                   2077: void do_store_sdr1 (CPUPPCState *env, target_ulong value)
                   2078: {
                   2079: #if defined (DEBUG_MMU)
                   2080:     if (loglevel != 0) {
1.1.1.4 ! root     2081:         fprintf(logfile, "%s: " ADDRX "\n", __func__, value);
1.1       root     2082:     }
                   2083: #endif
                   2084:     if (env->sdr1 != value) {
1.1.1.4 ! root     2085:         /* XXX: for PowerPC 64, should check that the HTABSIZE value
        !          2086:          *      is <= 28
        !          2087:          */
1.1       root     2088:         env->sdr1 = value;
1.1.1.4 ! root     2089:         tlb_flush(env, 1);
1.1       root     2090:     }
                   2091: }
                   2092: 
1.1.1.4 ! root     2093: #if 0 // Unused
1.1       root     2094: target_ulong do_load_sr (CPUPPCState *env, int srnum)
                   2095: {
                   2096:     return env->sr[srnum];
                   2097: }
1.1.1.4 ! root     2098: #endif
1.1       root     2099: 
                   2100: void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
                   2101: {
                   2102: #if defined (DEBUG_MMU)
                   2103:     if (loglevel != 0) {
1.1.1.4 ! root     2104:         fprintf(logfile, "%s: reg=%d " ADDRX " " ADDRX "\n",
        !          2105:                 __func__, srnum, value, env->sr[srnum]);
1.1       root     2106:     }
                   2107: #endif
                   2108:     if (env->sr[srnum] != value) {
                   2109:         env->sr[srnum] = value;
                   2110: #if !defined(FLUSH_ALL_TLBS) && 0
                   2111:         {
                   2112:             target_ulong page, end;
                   2113:             /* Invalidate 256 MB of virtual memory */
                   2114:             page = (16 << 20) * srnum;
                   2115:             end = page + (16 << 20);
                   2116:             for (; page != end; page += TARGET_PAGE_SIZE)
                   2117:                 tlb_flush_page(env, page);
                   2118:         }
                   2119: #else
1.1.1.4 ! root     2120:         tlb_flush(env, 1);
1.1       root     2121: #endif
                   2122:     }
                   2123: }
1.1.1.4 ! root     2124: #endif /* !defined (CONFIG_USER_ONLY) */
1.1       root     2125: 
1.1.1.4 ! root     2126: target_ulong ppc_load_xer (CPUPPCState *env)
1.1       root     2127: {
1.1.1.4 ! root     2128:     return hreg_load_xer(env);
1.1       root     2129: }
                   2130: 
1.1.1.4 ! root     2131: void ppc_store_xer (CPUPPCState *env, target_ulong value)
1.1       root     2132: {
1.1.1.4 ! root     2133:     hreg_store_xer(env, value);
1.1       root     2134: }
                   2135: 
1.1.1.4 ! root     2136: /* GDBstub can read and write MSR... */
        !          2137: void ppc_store_msr (CPUPPCState *env, target_ulong value)
1.1       root     2138: {
1.1.1.4 ! root     2139:     hreg_store_msr(env, value, 0);
1.1       root     2140: }
                   2141: 
                   2142: /*****************************************************************************/
                   2143: /* Exception processing */
                   2144: #if defined (CONFIG_USER_ONLY)
                   2145: void do_interrupt (CPUState *env)
                   2146: {
1.1.1.4 ! root     2147:     env->exception_index = POWERPC_EXCP_NONE;
        !          2148:     env->error_code = 0;
1.1       root     2149: }
1.1.1.4 ! root     2150: 
        !          2151: void ppc_hw_interrupt (CPUState *env)
1.1       root     2152: {
1.1.1.4 ! root     2153:     env->exception_index = POWERPC_EXCP_NONE;
        !          2154:     env->error_code = 0;
1.1       root     2155: }
1.1.1.4 ! root     2156: #else /* defined (CONFIG_USER_ONLY) */
        !          2157: static always_inline void dump_syscall (CPUState *env)
1.1       root     2158: {
1.1.1.4 ! root     2159:     fprintf(logfile, "syscall r0=" REGX " r3=" REGX " r4=" REGX
        !          2160:             " r5=" REGX " r6=" REGX " nip=" ADDRX "\n",
        !          2161:             ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
        !          2162:             ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), env->nip);
        !          2163: }
1.1       root     2164: 
1.1.1.4 ! root     2165: /* Note that this function should be greatly optimized
        !          2166:  * when called with a constant excp, from ppc_hw_interrupt
        !          2167:  */
        !          2168: static always_inline void powerpc_excp (CPUState *env,
        !          2169:                                         int excp_model, int excp)
        !          2170: {
        !          2171:     target_ulong msr, new_msr, vector;
        !          2172:     int srr0, srr1, asrr0, asrr1;
        !          2173:     int lpes0, lpes1, lev;
        !          2174: 
        !          2175:     if (0) {
        !          2176:         /* XXX: find a suitable condition to enable the hypervisor mode */
        !          2177:         lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
        !          2178:         lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
        !          2179:     } else {
        !          2180:         /* Those values ensure we won't enter the hypervisor mode */
        !          2181:         lpes0 = 0;
        !          2182:         lpes1 = 1;
1.1       root     2183:     }
1.1.1.4 ! root     2184: 
1.1       root     2185:     if (loglevel & CPU_LOG_INT) {
1.1.1.4 ! root     2186:         fprintf(logfile, "Raise exception at " ADDRX " => %08x (%02x)\n",
        !          2187:                 env->nip, excp, env->error_code);
1.1       root     2188:     }
1.1.1.4 ! root     2189:     msr = env->msr;
        !          2190:     new_msr = msr;
        !          2191:     srr0 = SPR_SRR0;
        !          2192:     srr1 = SPR_SRR1;
        !          2193:     asrr0 = -1;
        !          2194:     asrr1 = -1;
        !          2195:     msr &= ~((target_ulong)0x783F0000);
1.1       root     2196:     switch (excp) {
1.1.1.4 ! root     2197:     case POWERPC_EXCP_NONE:
        !          2198:         /* Should never happen */
        !          2199:         return;
        !          2200:     case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
        !          2201:         new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
        !          2202:         switch (excp_model) {
        !          2203:         case POWERPC_EXCP_40x:
        !          2204:             srr0 = SPR_40x_SRR2;
        !          2205:             srr1 = SPR_40x_SRR3;
        !          2206:             break;
        !          2207:         case POWERPC_EXCP_BOOKE:
        !          2208:             srr0 = SPR_BOOKE_CSRR0;
        !          2209:             srr1 = SPR_BOOKE_CSRR1;
        !          2210:             break;
        !          2211:         case POWERPC_EXCP_G2:
        !          2212:             break;
        !          2213:         default:
        !          2214:             goto excp_invalid;
1.1       root     2215:         }
                   2216:         goto store_next;
1.1.1.4 ! root     2217:     case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
1.1       root     2218:         if (msr_me == 0) {
1.1.1.4 ! root     2219:             /* Machine check exception is not enabled.
        !          2220:              * Enter checkstop state.
        !          2221:              */
        !          2222:             if (loglevel != 0) {
        !          2223:                 fprintf(logfile, "Machine check while not allowed. "
        !          2224:                         "Entering checkstop state\n");
        !          2225:             } else {
        !          2226:                 fprintf(stderr, "Machine check while not allowed. "
        !          2227:                         "Entering checkstop state\n");
        !          2228:             }
        !          2229:             env->halted = 1;
        !          2230:             env->interrupt_request |= CPU_INTERRUPT_EXITTB;
        !          2231:         }
        !          2232:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2233:         new_msr &= ~((target_ulong)1 << MSR_ME);
        !          2234:         if (0) {
        !          2235:             /* XXX: find a suitable condition to enable the hypervisor mode */
        !          2236:             new_msr |= (target_ulong)MSR_HVB;
        !          2237:         }
        !          2238:         /* XXX: should also have something loaded in DAR / DSISR */
        !          2239:         switch (excp_model) {
        !          2240:         case POWERPC_EXCP_40x:
        !          2241:             srr0 = SPR_40x_SRR2;
        !          2242:             srr1 = SPR_40x_SRR3;
        !          2243:             break;
        !          2244:         case POWERPC_EXCP_BOOKE:
        !          2245:             srr0 = SPR_BOOKE_MCSRR0;
        !          2246:             srr1 = SPR_BOOKE_MCSRR1;
        !          2247:             asrr0 = SPR_BOOKE_CSRR0;
        !          2248:             asrr1 = SPR_BOOKE_CSRR1;
        !          2249:             break;
        !          2250:         default:
        !          2251:             break;
1.1       root     2252:         }
                   2253:         goto store_next;
1.1.1.4 ! root     2254:     case POWERPC_EXCP_DSI:       /* Data storage exception                   */
1.1       root     2255: #if defined (DEBUG_EXCEPTIONS)
1.1.1.4 ! root     2256:         if (loglevel != 0) {
        !          2257:             fprintf(logfile, "DSI exception: DSISR=" ADDRX" DAR=" ADDRX "\n",
        !          2258:                     env->spr[SPR_DSISR], env->spr[SPR_DAR]);
        !          2259:         }
1.1       root     2260: #endif
1.1.1.4 ! root     2261:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2262:         if (lpes1 == 0)
        !          2263:             new_msr |= (target_ulong)MSR_HVB;
1.1       root     2264:         goto store_next;
1.1.1.4 ! root     2265:     case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
1.1       root     2266: #if defined (DEBUG_EXCEPTIONS)
1.1.1.4 ! root     2267:         if (loglevel != 0) {
        !          2268:             fprintf(logfile, "ISI exception: msr=" ADDRX ", nip=" ADDRX "\n",
        !          2269:                     msr, env->nip);
1.1       root     2270:         }
1.1.1.4 ! root     2271: #endif
        !          2272:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2273:         if (lpes1 == 0)
        !          2274:             new_msr |= (target_ulong)MSR_HVB;
        !          2275:         msr |= env->error_code;
1.1       root     2276:         goto store_next;
1.1.1.4 ! root     2277:     case POWERPC_EXCP_EXTERNAL:  /* External input                           */
        !          2278:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2279:         if (lpes0 == 1)
        !          2280:             new_msr |= (target_ulong)MSR_HVB;
        !          2281:         goto store_next;
        !          2282:     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
        !          2283:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2284:         if (lpes1 == 0)
        !          2285:             new_msr |= (target_ulong)MSR_HVB;
        !          2286:         /* XXX: this is false */
        !          2287:         /* Get rS/rD and rA from faulting opcode */
        !          2288:         env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
1.1       root     2289:         goto store_current;
1.1.1.4 ! root     2290:     case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
1.1       root     2291:         switch (env->error_code & ~0xF) {
1.1.1.4 ! root     2292:         case POWERPC_EXCP_FP:
        !          2293:             if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
1.1       root     2294: #if defined (DEBUG_EXCEPTIONS)
1.1.1.4 ! root     2295:                 if (loglevel != 0) {
        !          2296:                     fprintf(logfile, "Ignore floating point exception\n");
        !          2297:                 }
1.1       root     2298: #endif
1.1.1.4 ! root     2299:                 env->exception_index = POWERPC_EXCP_NONE;
        !          2300:                 env->error_code = 0;
1.1       root     2301:                 return;
1.1.1.4 ! root     2302:             }
        !          2303:             new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2304:             if (lpes1 == 0)
        !          2305:                 new_msr |= (target_ulong)MSR_HVB;
1.1       root     2306:             msr |= 0x00100000;
1.1.1.4 ! root     2307:             if (msr_fe0 == msr_fe1)
        !          2308:                 goto store_next;
        !          2309:             msr |= 0x00010000;
        !          2310:             break;
        !          2311:         case POWERPC_EXCP_INVAL:
        !          2312: #if defined (DEBUG_EXCEPTIONS)
        !          2313:             if (loglevel != 0) {
        !          2314:                 fprintf(logfile, "Invalid instruction at " ADDRX "\n",
        !          2315:                         env->nip);
        !          2316:             }
        !          2317: #endif
        !          2318:             new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2319:             if (lpes1 == 0)
        !          2320:                 new_msr |= (target_ulong)MSR_HVB;
1.1       root     2321:             msr |= 0x00080000;
1.1.1.4 ! root     2322:             break;
        !          2323:         case POWERPC_EXCP_PRIV:
        !          2324:             new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2325:             if (lpes1 == 0)
        !          2326:                 new_msr |= (target_ulong)MSR_HVB;
1.1       root     2327:             msr |= 0x00040000;
1.1.1.4 ! root     2328:             break;
        !          2329:         case POWERPC_EXCP_TRAP:
        !          2330:             new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2331:             if (lpes1 == 0)
        !          2332:                 new_msr |= (target_ulong)MSR_HVB;
1.1       root     2333:             msr |= 0x00020000;
                   2334:             break;
                   2335:         default:
                   2336:             /* Should never occur */
1.1.1.4 ! root     2337:             cpu_abort(env, "Invalid program exception %d. Aborting\n",
        !          2338:                       env->error_code);
        !          2339:             break;
        !          2340:         }
1.1       root     2341:         goto store_current;
1.1.1.4 ! root     2342:     case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
        !          2343:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2344:         if (lpes1 == 0)
        !          2345:             new_msr |= (target_ulong)MSR_HVB;
1.1       root     2346:         goto store_current;
1.1.1.4 ! root     2347:     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
1.1       root     2348:         /* NOTE: this is a temporary hack to support graphics OSI
                   2349:            calls from the MOL driver */
1.1.1.4 ! root     2350:         /* XXX: To be removed */
1.1       root     2351:         if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
                   2352:             env->osi_call) {
1.1.1.4 ! root     2353:             if (env->osi_call(env) != 0) {
        !          2354:                 env->exception_index = POWERPC_EXCP_NONE;
        !          2355:                 env->error_code = 0;
1.1       root     2356:                 return;
1.1.1.4 ! root     2357:             }
1.1       root     2358:         }
                   2359:         if (loglevel & CPU_LOG_INT) {
                   2360:             dump_syscall(env);
                   2361:         }
1.1.1.4 ! root     2362:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2363:         lev = env->error_code;
        !          2364:         if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
        !          2365:             new_msr |= (target_ulong)MSR_HVB;
        !          2366:         goto store_next;
        !          2367:     case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
        !          2368:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2369:         goto store_current;
        !          2370:     case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
        !          2371:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2372:         if (lpes1 == 0)
        !          2373:             new_msr |= (target_ulong)MSR_HVB;
1.1       root     2374:         goto store_next;
1.1.1.4 ! root     2375:     case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
        !          2376:         /* FIT on 4xx */
        !          2377: #if defined (DEBUG_EXCEPTIONS)
        !          2378:         if (loglevel != 0)
        !          2379:             fprintf(logfile, "FIT exception\n");
        !          2380: #endif
        !          2381:         new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
1.1       root     2382:         goto store_next;
1.1.1.4 ! root     2383:     case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
        !          2384: #if defined (DEBUG_EXCEPTIONS)
        !          2385:         if (loglevel != 0)
        !          2386:             fprintf(logfile, "WDT exception\n");
        !          2387: #endif
        !          2388:         switch (excp_model) {
        !          2389:         case POWERPC_EXCP_BOOKE:
        !          2390:             srr0 = SPR_BOOKE_CSRR0;
        !          2391:             srr1 = SPR_BOOKE_CSRR1;
        !          2392:             break;
        !          2393:         default:
        !          2394:             break;
        !          2395:         }
        !          2396:         new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
        !          2397:         goto store_next;
        !          2398:     case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
        !          2399:         new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
        !          2400:         goto store_next;
        !          2401:     case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
        !          2402:         new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
        !          2403:         goto store_next;
        !          2404:     case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
        !          2405:         switch (excp_model) {
        !          2406:         case POWERPC_EXCP_BOOKE:
        !          2407:             srr0 = SPR_BOOKE_DSRR0;
        !          2408:             srr1 = SPR_BOOKE_DSRR1;
        !          2409:             asrr0 = SPR_BOOKE_CSRR0;
        !          2410:             asrr1 = SPR_BOOKE_CSRR1;
        !          2411:             break;
        !          2412:         default:
        !          2413:             break;
        !          2414:         }
1.1       root     2415:         /* XXX: TODO */
1.1.1.4 ! root     2416:         cpu_abort(env, "Debug exception is not implemented yet !\n");
1.1       root     2417:         goto store_next;
1.1.1.4 ! root     2418:     case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
        !          2419:         new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
        !          2420:         goto store_current;
        !          2421:     case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
1.1       root     2422:         /* XXX: TODO */
1.1.1.4 ! root     2423:         cpu_abort(env, "Embedded floating point data exception "
1.1       root     2424:                   "is not implemented yet !\n");
                   2425:         goto store_next;
1.1.1.4 ! root     2426:     case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
1.1       root     2427:         /* XXX: TODO */
1.1.1.4 ! root     2428:         cpu_abort(env, "Embedded floating point round exception "
        !          2429:                   "is not implemented yet !\n");
1.1       root     2430:         goto store_next;
1.1.1.4 ! root     2431:     case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
        !          2432:         new_msr &= ~((target_ulong)1 << MSR_RI);
1.1       root     2433:         /* XXX: TODO */
                   2434:         cpu_abort(env,
1.1.1.4 ! root     2435:                   "Performance counter exception is not implemented yet !\n");
1.1       root     2436:         goto store_next;
1.1.1.4 ! root     2437:     case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
        !          2438:         /* XXX: TODO */
1.1       root     2439:         cpu_abort(env,
1.1.1.4 ! root     2440:                   "Embedded doorbell interrupt is not implemented yet !\n");
1.1       root     2441:         goto store_next;
1.1.1.4 ! root     2442:     case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
        !          2443:         switch (excp_model) {
        !          2444:         case POWERPC_EXCP_BOOKE:
        !          2445:             srr0 = SPR_BOOKE_CSRR0;
        !          2446:             srr1 = SPR_BOOKE_CSRR1;
1.1       root     2447:             break;
                   2448:         default:
                   2449:             break;
                   2450:         }
1.1.1.4 ! root     2451:         /* XXX: TODO */
        !          2452:         cpu_abort(env, "Embedded doorbell critical interrupt "
        !          2453:                   "is not implemented yet !\n");
        !          2454:         goto store_next;
        !          2455:     case POWERPC_EXCP_RESET:     /* System reset exception                   */
        !          2456:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2457:         if (0) {
        !          2458:             /* XXX: find a suitable condition to enable the hypervisor mode */
        !          2459:             new_msr |= (target_ulong)MSR_HVB;
1.1       root     2460:         }
1.1.1.4 ! root     2461:         goto store_next;
        !          2462:     case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
        !          2463:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2464:         if (lpes1 == 0)
        !          2465:             new_msr |= (target_ulong)MSR_HVB;
        !          2466:         goto store_next;
        !          2467:     case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
        !          2468:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2469:         if (lpes1 == 0)
        !          2470:             new_msr |= (target_ulong)MSR_HVB;
        !          2471:         goto store_next;
        !          2472:     case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
        !          2473:         srr0 = SPR_HSRR0;
        !          2474:         srr1 = SPR_HSRR1;
        !          2475:         new_msr |= (target_ulong)MSR_HVB;
        !          2476:         goto store_next;
        !          2477:     case POWERPC_EXCP_TRACE:     /* Trace exception                          */
        !          2478:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2479:         if (lpes1 == 0)
        !          2480:             new_msr |= (target_ulong)MSR_HVB;
        !          2481:         goto store_next;
        !          2482:     case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
        !          2483:         srr0 = SPR_HSRR0;
        !          2484:         srr1 = SPR_HSRR1;
        !          2485:         new_msr |= (target_ulong)MSR_HVB;
        !          2486:         goto store_next;
        !          2487:     case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
        !          2488:         srr0 = SPR_HSRR0;
        !          2489:         srr1 = SPR_HSRR1;
        !          2490:         new_msr |= (target_ulong)MSR_HVB;
        !          2491:         goto store_next;
        !          2492:     case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
        !          2493:         srr0 = SPR_HSRR0;
        !          2494:         srr1 = SPR_HSRR1;
        !          2495:         new_msr |= (target_ulong)MSR_HVB;
        !          2496:         goto store_next;
        !          2497:     case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
        !          2498:         srr0 = SPR_HSRR0;
        !          2499:         srr1 = SPR_HSRR1;
        !          2500:         new_msr |= (target_ulong)MSR_HVB;
        !          2501:         goto store_next;
        !          2502:     case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
        !          2503:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2504:         if (lpes1 == 0)
        !          2505:             new_msr |= (target_ulong)MSR_HVB;
        !          2506:         goto store_current;
        !          2507:     case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
        !          2508: #if defined (DEBUG_EXCEPTIONS)
        !          2509:         if (loglevel != 0)
        !          2510:             fprintf(logfile, "PIT exception\n");
        !          2511: #endif
        !          2512:         new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
        !          2513:         goto store_next;
        !          2514:     case POWERPC_EXCP_IO:        /* IO error exception                       */
        !          2515:         /* XXX: TODO */
        !          2516:         cpu_abort(env, "601 IO error exception is not implemented yet !\n");
        !          2517:         goto store_next;
        !          2518:     case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
        !          2519:         /* XXX: TODO */
        !          2520:         cpu_abort(env, "601 run mode exception is not implemented yet !\n");
        !          2521:         goto store_next;
        !          2522:     case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
        !          2523:         /* XXX: TODO */
        !          2524:         cpu_abort(env, "602 emulation trap exception "
        !          2525:                   "is not implemented yet !\n");
        !          2526:         goto store_next;
        !          2527:     case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
        !          2528:         new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
        !          2529:         if (lpes1 == 0) /* XXX: check this */
        !          2530:             new_msr |= (target_ulong)MSR_HVB;
        !          2531:         switch (excp_model) {
        !          2532:         case POWERPC_EXCP_602:
        !          2533:         case POWERPC_EXCP_603:
        !          2534:         case POWERPC_EXCP_603E:
        !          2535:         case POWERPC_EXCP_G2:
        !          2536:             goto tlb_miss_tgpr;
        !          2537:         case POWERPC_EXCP_7x5:
        !          2538:             goto tlb_miss;
        !          2539:         case POWERPC_EXCP_74xx:
        !          2540:             goto tlb_miss_74xx;
1.1       root     2541:         default:
1.1.1.4 ! root     2542:             cpu_abort(env, "Invalid instruction TLB miss exception\n");
1.1       root     2543:             break;
                   2544:         }
1.1.1.4 ! root     2545:         break;
        !          2546:     case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
        !          2547:         new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
        !          2548:         if (lpes1 == 0) /* XXX: check this */
        !          2549:             new_msr |= (target_ulong)MSR_HVB;
        !          2550:         switch (excp_model) {
        !          2551:         case POWERPC_EXCP_602:
        !          2552:         case POWERPC_EXCP_603:
        !          2553:         case POWERPC_EXCP_603E:
        !          2554:         case POWERPC_EXCP_G2:
        !          2555:             goto tlb_miss_tgpr;
        !          2556:         case POWERPC_EXCP_7x5:
        !          2557:             goto tlb_miss;
        !          2558:         case POWERPC_EXCP_74xx:
        !          2559:             goto tlb_miss_74xx;
1.1       root     2560:         default:
1.1.1.4 ! root     2561:             cpu_abort(env, "Invalid data load TLB miss exception\n");
1.1       root     2562:             break;
                   2563:         }
1.1.1.4 ! root     2564:         break;
        !          2565:     case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
        !          2566:         new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
        !          2567:         if (lpes1 == 0) /* XXX: check this */
        !          2568:             new_msr |= (target_ulong)MSR_HVB;
        !          2569:         switch (excp_model) {
        !          2570:         case POWERPC_EXCP_602:
        !          2571:         case POWERPC_EXCP_603:
        !          2572:         case POWERPC_EXCP_603E:
        !          2573:         case POWERPC_EXCP_G2:
        !          2574:         tlb_miss_tgpr:
        !          2575:             /* Swap temporary saved registers with GPRs */
        !          2576:             if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
        !          2577:                 new_msr |= (target_ulong)1 << MSR_TGPR;
        !          2578:                 hreg_swap_gpr_tgpr(env);
        !          2579:             }
        !          2580:             goto tlb_miss;
        !          2581:         case POWERPC_EXCP_7x5:
        !          2582:         tlb_miss:
1.1       root     2583: #if defined (DEBUG_SOFTWARE_TLB)
                   2584:             if (loglevel != 0) {
1.1.1.4 ! root     2585:                 const unsigned char *es;
        !          2586:                 target_ulong *miss, *cmp;
        !          2587:                 int en;
        !          2588:                 if (excp == POWERPC_EXCP_IFTLB) {
        !          2589:                     es = "I";
        !          2590:                     en = 'I';
        !          2591:                     miss = &env->spr[SPR_IMISS];
        !          2592:                     cmp = &env->spr[SPR_ICMP];
        !          2593:                 } else {
        !          2594:                     if (excp == POWERPC_EXCP_DLTLB)
        !          2595:                         es = "DL";
        !          2596:                     else
        !          2597:                         es = "DS";
        !          2598:                     en = 'D';
        !          2599:                     miss = &env->spr[SPR_DMISS];
        !          2600:                     cmp = &env->spr[SPR_DCMP];
        !          2601:                 }
        !          2602:                 fprintf(logfile, "6xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
        !          2603:                         " H1 " ADDRX " H2 " ADDRX " %08x\n",
        !          2604:                         es, en, *miss, en, *cmp,
        !          2605:                         env->spr[SPR_HASH1], env->spr[SPR_HASH2],
1.1       root     2606:                         env->error_code);
                   2607:             }
                   2608: #endif
                   2609:             msr |= env->crf[0] << 28;
                   2610:             msr |= env->error_code; /* key, D/I, S/L bits */
                   2611:             /* Set way using a LRU mechanism */
1.1.1.4 ! root     2612:             msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
1.1       root     2613:             break;
1.1.1.4 ! root     2614:         case POWERPC_EXCP_74xx:
        !          2615:         tlb_miss_74xx:
        !          2616: #if defined (DEBUG_SOFTWARE_TLB)
        !          2617:             if (loglevel != 0) {
        !          2618:                 const unsigned char *es;
        !          2619:                 target_ulong *miss, *cmp;
        !          2620:                 int en;
        !          2621:                 if (excp == POWERPC_EXCP_IFTLB) {
        !          2622:                     es = "I";
        !          2623:                     en = 'I';
        !          2624:                     miss = &env->spr[SPR_TLBMISS];
        !          2625:                     cmp = &env->spr[SPR_PTEHI];
        !          2626:                 } else {
        !          2627:                     if (excp == POWERPC_EXCP_DLTLB)
        !          2628:                         es = "DL";
        !          2629:                     else
        !          2630:                         es = "DS";
        !          2631:                     en = 'D';
        !          2632:                     miss = &env->spr[SPR_TLBMISS];
        !          2633:                     cmp = &env->spr[SPR_PTEHI];
        !          2634:                 }
        !          2635:                 fprintf(logfile, "74xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
        !          2636:                         " %08x\n",
        !          2637:                         es, en, *miss, en, *cmp, env->error_code);
        !          2638:             }
        !          2639: #endif
        !          2640:             msr |= env->error_code; /* key bit */
1.1       root     2641:             break;
                   2642:         default:
1.1.1.4 ! root     2643:             cpu_abort(env, "Invalid data store TLB miss exception\n");
1.1       root     2644:             break;
                   2645:         }
1.1.1.4 ! root     2646:         goto store_next;
        !          2647:     case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
        !          2648:         /* XXX: TODO */
        !          2649:         cpu_abort(env, "Floating point assist exception "
        !          2650:                   "is not implemented yet !\n");
        !          2651:         goto store_next;
        !          2652:     case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
        !          2653:         /* XXX: TODO */
        !          2654:         cpu_abort(env, "DABR exception is not implemented yet !\n");
        !          2655:         goto store_next;
        !          2656:     case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
        !          2657:         /* XXX: TODO */
        !          2658:         cpu_abort(env, "IABR exception is not implemented yet !\n");
        !          2659:         goto store_next;
        !          2660:     case POWERPC_EXCP_SMI:       /* System management interrupt              */
        !          2661:         /* XXX: TODO */
        !          2662:         cpu_abort(env, "SMI exception is not implemented yet !\n");
        !          2663:         goto store_next;
        !          2664:     case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
        !          2665:         /* XXX: TODO */
        !          2666:         cpu_abort(env, "Thermal management exception "
        !          2667:                   "is not implemented yet !\n");
        !          2668:         goto store_next;
        !          2669:     case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
        !          2670:         new_msr &= ~((target_ulong)1 << MSR_RI);
        !          2671:         if (lpes1 == 0)
        !          2672:             new_msr |= (target_ulong)MSR_HVB;
        !          2673:         /* XXX: TODO */
        !          2674:         cpu_abort(env,
        !          2675:                   "Performance counter exception is not implemented yet !\n");
        !          2676:         goto store_next;
        !          2677:     case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
        !          2678:         /* XXX: TODO */
        !          2679:         cpu_abort(env, "VPU assist exception is not implemented yet !\n");
        !          2680:         goto store_next;
        !          2681:     case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
        !          2682:         /* XXX: TODO */
        !          2683:         cpu_abort(env,
        !          2684:                   "970 soft-patch exception is not implemented yet !\n");
        !          2685:         goto store_next;
        !          2686:     case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
        !          2687:         /* XXX: TODO */
        !          2688:         cpu_abort(env,
        !          2689:                   "970 maintenance exception is not implemented yet !\n");
        !          2690:         goto store_next;
        !          2691:     case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
        !          2692:         /* XXX: TODO */
        !          2693:         cpu_abort(env, "Maskable external exception "
        !          2694:                   "is not implemented yet !\n");
        !          2695:         goto store_next;
        !          2696:     case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
        !          2697:         /* XXX: TODO */
        !          2698:         cpu_abort(env, "Non maskable external exception "
        !          2699:                   "is not implemented yet !\n");
        !          2700:         goto store_next;
1.1       root     2701:     default:
1.1.1.4 ! root     2702:     excp_invalid:
        !          2703:         cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
        !          2704:         break;
1.1       root     2705:     store_current:
                   2706:         /* save current instruction location */
1.1.1.4 ! root     2707:         env->spr[srr0] = env->nip - 4;
1.1       root     2708:         break;
                   2709:     store_next:
                   2710:         /* save next instruction location */
1.1.1.4 ! root     2711:         env->spr[srr0] = env->nip;
1.1       root     2712:         break;
                   2713:     }
1.1.1.4 ! root     2714:     /* Save MSR */
        !          2715:     env->spr[srr1] = msr;
        !          2716:     /* If any alternate SRR register are defined, duplicate saved values */
        !          2717:     if (asrr0 != -1)
        !          2718:         env->spr[asrr0] = env->spr[srr0];
        !          2719:     if (asrr1 != -1)
        !          2720:         env->spr[asrr1] = env->spr[srr1];
1.1       root     2721:     /* If we disactivated any translation, flush TLBs */
1.1.1.4 ! root     2722:     if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
1.1       root     2723:         tlb_flush(env, 1);
                   2724:     /* reload MSR with correct bits */
1.1.1.4 ! root     2725:     new_msr &= ~((target_ulong)1 << MSR_EE);
        !          2726:     new_msr &= ~((target_ulong)1 << MSR_PR);
        !          2727:     new_msr &= ~((target_ulong)1 << MSR_FP);
        !          2728:     new_msr &= ~((target_ulong)1 << MSR_FE0);
        !          2729:     new_msr &= ~((target_ulong)1 << MSR_SE);
        !          2730:     new_msr &= ~((target_ulong)1 << MSR_BE);
        !          2731:     new_msr &= ~((target_ulong)1 << MSR_FE1);
        !          2732:     new_msr &= ~((target_ulong)1 << MSR_IR);
        !          2733:     new_msr &= ~((target_ulong)1 << MSR_DR);
        !          2734: #if 0 /* Fix this: not on all targets */
        !          2735:     new_msr &= ~((target_ulong)1 << MSR_PMM);
        !          2736: #endif
        !          2737:     new_msr &= ~((target_ulong)1 << MSR_LE);
        !          2738:     if (msr_ile)
        !          2739:         new_msr |= (target_ulong)1 << MSR_LE;
        !          2740:     else
        !          2741:         new_msr &= ~((target_ulong)1 << MSR_LE);
1.1       root     2742:     /* Jump to handler */
1.1.1.4 ! root     2743:     vector = env->excp_vectors[excp];
        !          2744:     if (vector == (target_ulong)-1ULL) {
        !          2745:         cpu_abort(env, "Raised an exception without defined vector %d\n",
        !          2746:                   excp);
        !          2747:     }
        !          2748:     vector |= env->excp_prefix;
        !          2749: #if defined(TARGET_PPC64)
        !          2750:     if (excp_model == POWERPC_EXCP_BOOKE) {
        !          2751:         if (!msr_icm) {
        !          2752:             new_msr &= ~((target_ulong)1 << MSR_CM);
        !          2753:             vector = (uint32_t)vector;
        !          2754:         } else {
        !          2755:             new_msr |= (target_ulong)1 << MSR_CM;
        !          2756:         }
        !          2757:     } else {
        !          2758:         if (!msr_isf) {
        !          2759:             new_msr &= ~((target_ulong)1 << MSR_SF);
        !          2760:             vector = (uint32_t)vector;
        !          2761:         } else {
        !          2762:             new_msr |= (target_ulong)1 << MSR_SF;
        !          2763:         }
        !          2764:     }
        !          2765: #endif
        !          2766:     /* XXX: we don't use hreg_store_msr here as already have treated
        !          2767:      *      any special case that could occur. Just store MSR and update hflags
        !          2768:      */
        !          2769:     env->msr = new_msr & env->msr_mask;
        !          2770:     hreg_compute_hflags(env);
        !          2771:     env->nip = vector;
        !          2772:     /* Reset exception state */
        !          2773:     env->exception_index = POWERPC_EXCP_NONE;
        !          2774:     env->error_code = 0;
        !          2775: }
        !          2776: 
        !          2777: void do_interrupt (CPUState *env)
        !          2778: {
        !          2779:     powerpc_excp(env, env->excp_model, env->exception_index);
        !          2780: }
        !          2781: 
        !          2782: void ppc_hw_interrupt (CPUPPCState *env)
        !          2783: {
        !          2784:     int hdice;
        !          2785: 
        !          2786: #if 0
        !          2787:     if (loglevel & CPU_LOG_INT) {
        !          2788:         fprintf(logfile, "%s: %p pending %08x req %08x me %d ee %d\n",
        !          2789:                 __func__, env, env->pending_interrupts,
        !          2790:                 env->interrupt_request, (int)msr_me, (int)msr_ee);
        !          2791:     }
        !          2792: #endif
        !          2793:     /* External reset */
        !          2794:     if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
        !          2795:         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
        !          2796:         powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
        !          2797:         return;
        !          2798:     }
        !          2799:     /* Machine check exception */
        !          2800:     if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
        !          2801:         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
        !          2802:         powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
        !          2803:         return;
        !          2804:     }
        !          2805: #if 0 /* TODO */
        !          2806:     /* External debug exception */
        !          2807:     if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
        !          2808:         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
        !          2809:         powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
        !          2810:         return;
        !          2811:     }
        !          2812: #endif
        !          2813:     if (0) {
        !          2814:         /* XXX: find a suitable condition to enable the hypervisor mode */
        !          2815:         hdice = env->spr[SPR_LPCR] & 1;
        !          2816:     } else {
        !          2817:         hdice = 0;
        !          2818:     }
        !          2819:     if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
        !          2820:         /* Hypervisor decrementer exception */
        !          2821:         if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
        !          2822:             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
        !          2823:             powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
        !          2824:             return;
        !          2825:         }
        !          2826:     }
        !          2827:     if (msr_ce != 0) {
        !          2828:         /* External critical interrupt */
        !          2829:         if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
        !          2830:             /* Taking a critical external interrupt does not clear the external
        !          2831:              * critical interrupt status
        !          2832:              */
        !          2833: #if 0
        !          2834:             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
        !          2835: #endif
        !          2836:             powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
        !          2837:             return;
        !          2838:         }
        !          2839:     }
        !          2840:     if (msr_ee != 0) {
        !          2841:         /* Watchdog timer on embedded PowerPC */
        !          2842:         if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
        !          2843:             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
        !          2844:             powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
        !          2845:             return;
        !          2846:         }
        !          2847:         if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
        !          2848:             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
        !          2849:             powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
        !          2850:             return;
        !          2851:         }
        !          2852:         /* Fixed interval timer on embedded PowerPC */
        !          2853:         if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
        !          2854:             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
        !          2855:             powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
        !          2856:             return;
        !          2857:         }
        !          2858:         /* Programmable interval timer on embedded PowerPC */
        !          2859:         if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
        !          2860:             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
        !          2861:             powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
        !          2862:             return;
        !          2863:         }
        !          2864:         /* Decrementer exception */
        !          2865:         if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
        !          2866:             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
        !          2867:             powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
        !          2868:             return;
        !          2869:         }
        !          2870:         /* External interrupt */
        !          2871:         if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
        !          2872:             /* Taking an external interrupt does not clear the external
        !          2873:              * interrupt status
        !          2874:              */
        !          2875: #if 0
        !          2876:             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
        !          2877: #endif
        !          2878:             powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
        !          2879:             return;
        !          2880:         }
        !          2881:         if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
        !          2882:             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
        !          2883:             powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
        !          2884:             return;
        !          2885:         }
        !          2886:         if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
        !          2887:             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
        !          2888:             powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
        !          2889:             return;
        !          2890:         }
        !          2891:         /* Thermal interrupt */
        !          2892:         if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
        !          2893:             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
        !          2894:             powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
        !          2895:             return;
        !          2896:         }
        !          2897:     }
1.1       root     2898: }
                   2899: #endif /* !CONFIG_USER_ONLY */
1.1.1.4 ! root     2900: 
        !          2901: void cpu_dump_EA (target_ulong EA)
        !          2902: {
        !          2903:     FILE *f;
        !          2904: 
        !          2905:     if (logfile) {
        !          2906:         f = logfile;
        !          2907:     } else {
        !          2908:         f = stdout;
        !          2909:         return;
        !          2910:     }
        !          2911:     fprintf(f, "Memory access at address " ADDRX "\n", EA);
        !          2912: }
        !          2913: 
        !          2914: void cpu_dump_rfi (target_ulong RA, target_ulong msr)
        !          2915: {
        !          2916:     FILE *f;
        !          2917: 
        !          2918:     if (logfile) {
        !          2919:         f = logfile;
        !          2920:     } else {
        !          2921:         f = stdout;
        !          2922:         return;
        !          2923:     }
        !          2924:     fprintf(f, "Return from exception at " ADDRX " with flags " ADDRX "\n",
        !          2925:             RA, msr);
        !          2926: }
        !          2927: 
        !          2928: void cpu_ppc_reset (void *opaque)
        !          2929: {
        !          2930:     CPUPPCState *env;
        !          2931:     target_ulong msr;
        !          2932: 
        !          2933:     env = opaque;
        !          2934:     msr = (target_ulong)0;
        !          2935:     if (0) {
        !          2936:         /* XXX: find a suitable condition to enable the hypervisor mode */
        !          2937:         msr |= (target_ulong)MSR_HVB;
        !          2938:     }
        !          2939:     msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
        !          2940:     msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
        !          2941:     msr |= (target_ulong)1 << MSR_EP;
        !          2942: #if defined (DO_SINGLE_STEP) && 0
        !          2943:     /* Single step trace mode */
        !          2944:     msr |= (target_ulong)1 << MSR_SE;
        !          2945:     msr |= (target_ulong)1 << MSR_BE;
        !          2946: #endif
        !          2947: #if defined(CONFIG_USER_ONLY)
        !          2948:     msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
        !          2949:     msr |= (target_ulong)1 << MSR_PR;
        !          2950: #else
        !          2951:     env->nip = env->hreset_vector | env->excp_prefix;
        !          2952:     if (env->mmu_model != POWERPC_MMU_REAL)
        !          2953:         ppc_tlb_invalidate_all(env);
        !          2954: #endif
        !          2955:     env->msr = msr;
        !          2956:     hreg_compute_hflags(env);
        !          2957:     env->reserve = (target_ulong)-1ULL;
        !          2958:     /* Be sure no exception or interrupt is pending */
        !          2959:     env->pending_interrupts = 0;
        !          2960:     env->exception_index = POWERPC_EXCP_NONE;
        !          2961:     env->error_code = 0;
        !          2962:     /* Flush all TLBs */
        !          2963:     tlb_flush(env, 1);
        !          2964: }
        !          2965: 
        !          2966: CPUPPCState *cpu_ppc_init (const char *cpu_model)
        !          2967: {
        !          2968:     CPUPPCState *env;
        !          2969:     const ppc_def_t *def;
        !          2970: 
        !          2971:     def = cpu_ppc_find_by_name(cpu_model);
        !          2972:     if (!def)
        !          2973:         return NULL;
        !          2974: 
        !          2975:     env = qemu_mallocz(sizeof(CPUPPCState));
        !          2976:     if (!env)
        !          2977:         return NULL;
        !          2978:     cpu_exec_init(env);
        !          2979:     env->cpu_model_str = cpu_model;
        !          2980:     cpu_ppc_register_internal(env, def);
        !          2981:     cpu_ppc_reset(env);
        !          2982:     return env;
        !          2983: }
        !          2984: 
        !          2985: void cpu_ppc_close (CPUPPCState *env)
        !          2986: {
        !          2987:     /* Should also remove all opcode tables... */
        !          2988:     qemu_free(env);
        !          2989: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.