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

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

unix.superglobalmegacorp.com

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