File:  [Qemu by Fabrice Bellard] / qemu / target-ppc / helper.c
Revision 1.1.1.8 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:21:16 2018 UTC (3 years, 8 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0125, HEAD
qemu 0.12.5

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

unix.superglobalmegacorp.com