qemu/target-ppc/helper.c
<<
>>
Prefs
   1/*
   2 *  PowerPC emulation helpers for qemu.
   3 *
   4 *  Copyright (c) 2003-2007 Jocelyn Mayer
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19#include <stdarg.h>
  20#include <stdlib.h>
  21#include <stdio.h>
  22#include <string.h>
  23#include <inttypes.h>
  24
  25#include "cpu.h"
  26#include "helper_regs.h"
  27#include "qemu-common.h"
  28#include "kvm.h"
  29
  30//#define DEBUG_MMU
  31//#define DEBUG_BATS
  32//#define DEBUG_SLB
  33//#define DEBUG_SOFTWARE_TLB
  34//#define DUMP_PAGE_TABLES
  35//#define DEBUG_EXCEPTIONS
  36//#define FLUSH_ALL_TLBS
  37
  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
  71/*****************************************************************************/
  72/* PowerPC Hypercall emulation */
  73
  74void (*cpu_ppc_hypercall)(CPUState *);
  75
  76/*****************************************************************************/
  77/* PowerPC MMU emulation */
  78
  79#if defined(CONFIG_USER_ONLY)
  80int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
  81                              int mmu_idx, int is_softmmu)
  82{
  83    int exception, error_code;
  84
  85    if (rw == 2) {
  86        exception = POWERPC_EXCP_ISI;
  87        error_code = 0x40000000;
  88    } else {
  89        exception = POWERPC_EXCP_DSI;
  90        error_code = 0x40000000;
  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;
  98
  99    return 1;
 100}
 101
 102#else
 103/* Common routines used by software and hardware TLBs emulation */
 104static inline int pte_is_valid(target_ulong pte0)
 105{
 106    return pte0 & 0x80000000 ? 1 : 0;
 107}
 108
 109static inline void pte_invalidate(target_ulong *pte0)
 110{
 111    *pte0 &= ~0x80000000;
 112}
 113
 114#if defined(TARGET_PPC64)
 115static inline int pte64_is_valid(target_ulong pte0)
 116{
 117    return pte0 & 0x0000000000000001ULL ? 1 : 0;
 118}
 119
 120static inline void pte64_invalidate(target_ulong *pte0)
 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
 133static inline int pp_check(int key, int pp, int nx)
 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
 173static inline int check_prot(int prot, int rw, int access_type)
 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
 197static inline int _pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0,
 198                             target_ulong pte1, int h, int rw, int type)
 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);
 222            ctx->nx  = (pte1 >> 2) & 1; /* No execute bit */
 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)) {
 235                    qemu_log("Bad RPN/WIMG/PP\n");
 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 */
 247                LOG_MMU("PTE access granted !\n");
 248            } else {
 249                /* Access right violation */
 250                LOG_MMU("PTE access rejected\n");
 251            }
 252        }
 253    }
 254
 255    return ret;
 256}
 257
 258static inline int pte32_check(mmu_ctx_t *ctx, target_ulong pte0,
 259                              target_ulong pte1, int h, int rw, int type)
 260{
 261    return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
 262}
 263
 264#if defined(TARGET_PPC64)
 265static inline int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
 266                              target_ulong pte1, int h, int rw, int type)
 267{
 268    return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
 269}
 270#endif
 271
 272static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
 273                                   int ret, int rw)
 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 */
 298static inline int ppc6xx_tlb_getnum(CPUState *env, target_ulong eaddr, int way,
 299                                    int is_code)
 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
 314static inline void ppc6xx_tlb_invalidate_all(CPUState *env)
 315{
 316    ppc6xx_tlb_t *tlb;
 317    int nr, max;
 318
 319    //LOG_SWTLB("Invalidate all TLBs\n");
 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++) {
 325        tlb = &env->tlb.tlb6[nr];
 326        pte_invalidate(&tlb->pte0);
 327    }
 328    tlb_flush(env, 1);
 329}
 330
 331static inline void __ppc6xx_tlb_invalidate_virt(CPUState *env,
 332                                                target_ulong eaddr,
 333                                                int is_code, int match_epn)
 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);
 342        tlb = &env->tlb.tlb6[nr];
 343        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
 344            LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
 345                      env->nb_tlb, eaddr);
 346            pte_invalidate(&tlb->pte0);
 347            tlb_flush_page(env, tlb->EPN);
 348        }
 349    }
 350#else
 351    /* XXX: PowerPC specification say this is valid as well */
 352    ppc6xx_tlb_invalidate_all(env);
 353#endif
 354}
 355
 356static inline void ppc6xx_tlb_invalidate_virt(CPUState *env,
 357                                              target_ulong eaddr, int is_code)
 358{
 359    __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
 360}
 361
 362void 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);
 369    tlb = &env->tlb.tlb6[nr];
 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);
 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
 381static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
 382                                   target_ulong eaddr, int rw, int access_type)
 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);
 393        tlb = &env->tlb.tlb6[nr];
 394        /* This test "emulates" the PTE index match for hardware TLBs */
 395        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
 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);
 400            continue;
 401        }
 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');
 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:
 433        LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
 434                  ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
 435        /* Update page flags */
 436        pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, rw);
 437    }
 438
 439    return ret;
 440}
 441
 442/* Perform BAT hit & translation */
 443static inline void bat_size_prot(CPUState *env, target_ulong *blp, int *validp,
 444                                 int *protp, target_ulong *BATu,
 445                                 target_ulong *BATl)
 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
 468static inline void bat_601_size_prot(CPUState *env, target_ulong *blp,
 469                                     int *validp, int *protp,
 470                                     target_ulong *BATu, target_ulong *BATl)
 471{
 472    target_ulong bl;
 473    int key, pp, valid, prot;
 474
 475    bl = (*BATl & 0x0000003F) << 17;
 476    LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
 477             (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
 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
 493static inline int get_bat(CPUState *env, mmu_ctx_t *ctx, target_ulong virtual,
 494                          int rw, int type)
 495{
 496    target_ulong *BATlt, *BATut, *BATu, *BATl;
 497    target_ulong BEPIl, BEPIu, bl;
 498    int i, valid, prot;
 499    int ret = -1;
 500
 501    LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
 502             type == ACCESS_CODE ? 'I' : 'D', virtual);
 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    }
 513    for (i = 0; i < env->nb_BATs; i++) {
 514        BATu = &BATut[i];
 515        BATl = &BATlt[i];
 516        BEPIu = *BATu & 0xF0000000;
 517        BEPIl = *BATu & 0x0FFE0000;
 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        }
 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);
 526        if ((virtual & 0xF0000000) == BEPIu &&
 527            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
 528            /* BAT matches */
 529            if (valid != 0) {
 530                /* Get physical address */
 531                ctx->raddr = (*BATl & 0xF0000000) |
 532                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
 533                    (virtual & 0x0001F000);
 534                /* Compute access rights */
 535                ctx->prot = prot;
 536                ret = check_prot(ctx->prot, rw, type);
 537                if (ret == 0)
 538                    LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
 539                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
 540                             ctx->prot & PAGE_WRITE ? 'W' : '-');
 541                break;
 542            }
 543        }
 544    }
 545    if (ret < 0) {
 546#if defined(DEBUG_BATS)
 547        if (qemu_log_enabled()) {
 548            LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
 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;
 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",
 558                         __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
 559                         *BATu, *BATl, BEPIu, BEPIl, bl);
 560            }
 561        }
 562#endif
 563    }
 564    /* No hit */
 565    return ret;
 566}
 567
 568static 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
 575/* PTE table lookup */
 576static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
 577                            int rw, int type, int target_page_bits)
 578{
 579    target_phys_addr_t pteg_off;
 580    target_ulong pte0, pte1;
 581    int i, good = -1;
 582    int ret, r;
 583
 584    ret = -1; /* No entry found */
 585    pteg_off = get_pteg_offset(env, ctx->hash[h],
 586                               is_64b ? HASH_PTE_SIZE_64 : HASH_PTE_SIZE_32);
 587    for (i = 0; i < 8; i++) {
 588#if defined(TARGET_PPC64)
 589        if (is_64b) {
 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            }
 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
 604            r = pte64_check(ctx, pte0, pte1, h, rw, type);
 605            LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
 606                    TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
 607                    pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
 608                    (int)((pte0 >> 1) & 1), ctx->ptem);
 609        } else
 610#endif
 611        {
 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            }
 619            r = pte32_check(ctx, pte0, pte1, h, rw, type);
 620            LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
 621                    TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
 622                    pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
 623                    (int)((pte0 >> 6) & 1), ctx->ptem);
 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;
 647        }
 648    }
 649    if (good != -1) {
 650    done:
 651        LOG_MMU("found PTE at addr " TARGET_FMT_lx " prot=%01x ret=%d\n",
 652                ctx->raddr, ctx->prot, ret);
 653        /* Update page flags */
 654        pte1 = ctx->raddr;
 655        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
 656#if defined(TARGET_PPC64)
 657            if (is_64b) {
 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                }
 665            } else
 666#endif
 667            {
 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                }
 675            }
 676        }
 677    }
 678
 679    return ret;
 680}
 681
 682static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
 683                           int type, int target_page_bits)
 684{
 685#if defined(TARGET_PPC64)
 686    if (env->mmu_model & POWERPC_MMU_64)
 687        return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
 688#endif
 689
 690    return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
 691}
 692
 693#if defined(TARGET_PPC64)
 694static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
 695{
 696    uint64_t esid_256M, esid_1T;
 697    int n;
 698
 699    LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
 700
 701    esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
 702    esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
 703
 704    for (n = 0; n < env->slb_nr; n++) {
 705        ppc_slb_t *slb = &env->slb[n];
 706
 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;
 717        }
 718    }
 719
 720    return NULL;
 721}
 722
 723void 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++) {
 730        ppc_slb_t *slb = &env->slb[n];
 731
 732        if (slb->esid & SLB_ESID_V) {
 733            slb->esid &= ~SLB_ESID_V;
 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
 745void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
 746{
 747    ppc_slb_t *slb;
 748
 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);
 762    }
 763}
 764
 765int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
 766{
 767    int slot = rb & 0xfff;
 768    ppc_slb_t *slb = &env->slb[slot];
 769
 770    if (rb & (0x1000 - env->slb_nr)) {
 771        return -1; /* Reserved bits set or slot too high */
 772    }
 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);
 787
 788    return 0;
 789}
 790
 791int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
 792{
 793    int slot = rb & 0xfff;
 794    ppc_slb_t *slb = &env->slb[slot];
 795
 796    if (slot >= env->slb_nr) {
 797        return -1;
 798    }
 799
 800    *rt = slb->esid;
 801    return 0;
 802}
 803
 804int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
 805{
 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;
 815}
 816#endif /* defined(TARGET_PPC64) */
 817
 818/* Perform segment based translation */
 819static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
 820                              target_ulong eaddr, int rw, int type)
 821{
 822    target_phys_addr_t hash;
 823    target_ulong vsid;
 824    int ds, pr, target_page_bits;
 825    int ret, ret2;
 826
 827    pr = msr_pr;
 828    ctx->eaddr = eaddr;
 829#if defined(TARGET_PPC64)
 830    if (env->mmu_model & POWERPC_MMU_64) {
 831        ppc_slb_t *slb;
 832        target_ulong pageaddr;
 833        int segment_bits;
 834
 835        LOG_MMU("Check SLBs\n");
 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));
 853        ds = 0;
 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));
 866    } else
 867#endif /* defined(TARGET_PPC64) */
 868    {
 869        target_ulong sr, pgidx;
 870
 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;
 877        target_page_bits = TARGET_PAGE_BITS;
 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);
 883        pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
 884        hash = vsid ^ pgidx;
 885        ctx->ptem = (vsid << 7) | (pgidx >> 10);
 886    }
 887    LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
 888            ctx->key, ds, ctx->nx, vsid);
 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 */
 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
 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 {
 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]);
 912                /* Primary table lookup */
 913                ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
 914                if (ret < 0) {
 915                    /* Secondary table lookup */
 916                    if (eaddr != 0xEFFFFFFF)
 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]);
 921                    ret2 = find_pte(env, ctx, 1, rw, type,
 922                                    target_page_bits);
 923                    if (ret2 != -1)
 924                        ret = ret2;
 925                }
 926            }
 927#if defined (DUMP_PAGE_TABLES)
 928            if (qemu_log_enabled()) {
 929                target_phys_addr_t curaddr;
 930                uint32_t a0, a1, a2, a3;
 931                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
 932                         "\n", sdr, mask + 0x80);
 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) {
 940                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
 941                                 curaddr, a0, a1, a2, a3);
 942                    }
 943                }
 944            }
 945#endif
 946        } else {
 947            LOG_MMU("No access allowed\n");
 948            ret = -3;
 949        }
 950    } else {
 951        target_ulong sr;
 952        LOG_MMU("direct store...\n");
 953        /* Direct-store segment : absolutely *BUGGY* for now */
 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
 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:
 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             */
 987            ctx->raddr = eaddr;
 988            return 0;
 989        case ACCESS_EXT:
 990            /* eciwx or ecowx */
 991            return -4;
 992        default:
 993            qemu_log("ERROR: instruction should not need "
 994                        "address translation\n");
 995            return -4;
 996        }
 997        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
 998            ctx->raddr = eaddr;
 999            ret = 2;
1000        } else {
1001            ret = -2;
1002        }
1003    }
1004
1005    return ret;
1006}
1007
1008/* Generic TLB check function for embedded PowerPC implementations */
1009int 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)
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);
1021    LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
1022              " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
1023              mask, (uint32_t)tlb->PID, tlb->prot);
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 */
1042int 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++) {
1051        tlb = &env->tlb.tlbe[i];
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 */
1062static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1063{
1064    ppcemb_tlb_t *tlb;
1065    int i;
1066
1067    for (i = 0; i < env->nb_tlb; i++) {
1068        tlb = &env->tlb.tlbe[i];
1069        tlb->prot &= ~PAGE_VALID;
1070    }
1071    tlb_flush(env, 1);
1072}
1073
1074static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1075                                              target_ulong eaddr, uint32_t pid)
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++) {
1084        tlb = &env->tlb.tlbe[i];
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
1098static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
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++) {
1109        tlb = &env->tlb.tlbe[i];
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;
1114        zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
1115        LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
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) {
1130                /* Raise Zone protection fault.  */
1131                env->spr[SPR_40x_ESR] = 1 << 22;
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);
1142            if (ret == -2)
1143                env->spr[SPR_40x_ESR] = 0;
1144            break;
1145        }
1146        if (ret >= 0) {
1147            ctx->raddr = raddr;
1148            LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1149                      " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1150                      ret);
1151            return 0;
1152        }
1153    }
1154    LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1155              " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1156
1157    return ret;
1158}
1159
1160void 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
1169static 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
1197found_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
1239static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1240                                          target_ulong address, int rw,
1241                                          int access_type)
1242{
1243    ppcemb_tlb_t *tlb;
1244    target_phys_addr_t raddr;
1245    int i, ret;
1246
1247    ret = -1;
1248    raddr = (target_phys_addr_t)-1ULL;
1249    for (i = 0; i < env->nb_tlb; i++) {
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
1271void 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                }
1284            }
1285        }
1286        tlb += booke206_tlb_size(env, i);
1287    }
1288
1289    tlb_flush(env, 1);
1290}
1291
1292target_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 */
1310int 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
1343static 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
1371found_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
1429static 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;
1449            }
1450        }
1451    }
1452
1453found_tlb:
1454
1455    if (ret >= 0) {
1456        ctx->raddr = raddr;
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    }
1464
1465    return ret;
1466}
1467
1468static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1469                                 target_ulong eaddr, int rw)
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:
1489    case POWERPC_MMU_2_06:
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;
1523    case POWERPC_MMU_BOOKE206:
1524        cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
1525        break;
1526    default:
1527        cpu_abort(env, "Unknown or invalid MMU model\n");
1528        return -1;
1529    }
1530
1531    return ret;
1532}
1533
1534int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1535                          int rw, int access_type)
1536{
1537    int ret;
1538
1539#if 0
1540    qemu_log("%s\n", __func__);
1541#endif
1542    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1543        (access_type != ACCESS_CODE && msr_dr == 0)) {
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);
1549        } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1550            ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1551                                                   access_type);
1552        } else {
1553            /* No address translation.  */
1554            ret = check_physical(env, ctx, eaddr, rw);
1555        }
1556    } else {
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:
1563            /* Try to find a BAT */
1564            if (env->nb_BATs != 0)
1565                ret = get_bat(env, ctx, eaddr, rw, access_type);
1566#if defined(TARGET_PPC64)
1567        case POWERPC_MMU_620:
1568        case POWERPC_MMU_64B:
1569        case POWERPC_MMU_2_06:
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;
1585        case POWERPC_MMU_BOOKE206:
1586            ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1587                                               access_type);
1588            break;
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;
1599        }
1600    }
1601#if 0
1602    qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1603             __func__, eaddr, ret, ctx->raddr);
1604#endif
1605
1606    return ret;
1607}
1608
1609target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1610{
1611    mmu_ctx_t ctx;
1612
1613    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1614        return -1;
1615
1616    return ctx.raddr & TARGET_PAGE_MASK;
1617}
1618
1619static 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
1659/* Perform address translation */
1660int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1661                              int mmu_idx, int is_softmmu)
1662{
1663    mmu_ctx_t ctx;
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 */
1673        access_type = env->access_type;
1674    }
1675    ret = get_physical_address(env, &ctx, address, rw, access_type);
1676    if (ret == 0) {
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;
1681    } else if (ret < 0) {
1682        LOG_MMU_STATE(env);
1683        if (access_type == ACCESS_CODE) {
1684            switch (ret) {
1685            case -1:
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:
1709                case POWERPC_MMU_2_06:
1710#endif
1711                    env->exception_index = POWERPC_EXCP_ISI;
1712                    env->error_code = 0x40000000;
1713                    break;
1714                case POWERPC_MMU_BOOKE206:
1715                    booke206_update_mas_tlb_miss(env, address, rw);
1716                    /* fall through */
1717                case POWERPC_MMU_BOOKE:
1718                    env->exception_index = POWERPC_EXCP_ITLB;
1719                    env->error_code = 0;
1720                    env->spr[SPR_BOOKE_DEAR] = address;
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                }
1734                break;
1735            case -2:
1736                /* Access rights violation */
1737                env->exception_index = POWERPC_EXCP_ISI;
1738                env->error_code = 0x08000000;
1739                break;
1740            case -3:
1741                /* No execute protection violation */
1742                if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1743                    (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1744                    env->spr[SPR_BOOKE_ESR] = 0x00000000;
1745                }
1746                env->exception_index = POWERPC_EXCP_ISI;
1747                env->error_code = 0x10000000;
1748                break;
1749            case -4:
1750                /* Direct store exception */
1751                /* No code fetch is allowed in direct-store areas */
1752                env->exception_index = POWERPC_EXCP_ISI;
1753                env->error_code = 0x10000000;
1754                break;
1755#if defined(TARGET_PPC64)
1756            case -5:
1757                /* No match in segment table */
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                }
1766                break;
1767#endif
1768            }
1769        } else {
1770            switch (ret) {
1771            case -1:
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;
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);
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:
1819                case POWERPC_MMU_2_06:
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;
1833                case POWERPC_MMU_BOOKE206:
1834                    booke206_update_mas_tlb_miss(env, address, rw);
1835                    /* fall through */
1836                case POWERPC_MMU_BOOKE:
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;
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                }
1850                break;
1851            case -2:
1852                /* Access rights violation */
1853                env->exception_index = POWERPC_EXCP_DSI;
1854                env->error_code = 0;
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                    }
1861                } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1862                           (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1863                    env->spr[SPR_BOOKE_DEAR] = address;
1864                    env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
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                }
1873                break;
1874            case -4:
1875                /* Direct store exception */
1876                switch (access_type) {
1877                case ACCESS_FLOAT:
1878                    /* Floating point load/store */
1879                    env->exception_index = POWERPC_EXCP_ALIGN;
1880                    env->error_code = POWERPC_EXCP_ALIGN_FP;
1881                    env->spr[SPR_DAR] = address;
1882                    break;
1883                case ACCESS_RES:
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;
1892                    break;
1893                case ACCESS_EXT:
1894                    /* eciwx or ecowx */
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;
1902                    break;
1903                default:
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;
1909                    break;
1910                }
1911                break;
1912#if defined(TARGET_PPC64)
1913            case -5:
1914                /* No match in segment table */
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                }
1929                break;
1930#endif
1931            }
1932        }
1933#if 0
1934        printf("%s: set exception to %d %02x\n", __func__,
1935               env->exception, env->error_code);
1936#endif
1937        ret = 1;
1938    }
1939
1940    return ret;
1941}
1942
1943/*****************************************************************************/
1944/* BATs management */
1945#if !defined(FLUSH_ALL_TLBS)
1946static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1947                                     target_ulong mask)
1948{
1949    target_ulong base, end, page;
1950
1951    base = BATu & ~0x0001FFFF;
1952    end = base + mask + 0x00020000;
1953    LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1954             TARGET_FMT_lx ")\n", base, end, mask);
1955    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1956        tlb_flush_page(env, page);
1957    LOG_BATS("Flush done\n");
1958}
1959#endif
1960
1961static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1962                                  target_ulong value)
1963{
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);
1966}
1967
1968void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
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);
1988#else
1989        tlb_flush(env, 1);
1990#endif
1991    }
1992}
1993
1994void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1995{
1996    dump_store_bat(env, 'I', 1, nr, value);
1997    env->IBAT[1][nr] = value;
1998}
1999
2000void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
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
2026void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
2027{
2028    dump_store_bat(env, 'D', 1, nr, value);
2029    env->DBAT[1][nr] = value;
2030}
2031
2032void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
2033{
2034    target_ulong mask;
2035#if defined(FLUSH_ALL_TLBS)
2036    int do_inval;
2037#endif
2038
2039    dump_store_bat(env, 'I', 0, nr, value);
2040    if (env->IBAT[0][nr] != value) {
2041#if defined(FLUSH_ALL_TLBS)
2042        do_inval = 0;
2043#endif
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    }
2071}
2072
2073void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
2074{
2075    target_ulong mask;
2076#if defined(FLUSH_ALL_TLBS)
2077    int do_inval;
2078#endif
2079
2080    dump_store_bat(env, 'I', 1, nr, value);
2081    if (env->IBAT[1][nr] != value) {
2082#if defined(FLUSH_ALL_TLBS)
2083        do_inval = 0;
2084#endif
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 */
2112void 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:
2131        tlb_flush(env, 1);
2132        break;
2133    case POWERPC_MMU_BOOKE206:
2134        booke206_flush_tlb(env, -1, 0);
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:
2141    case POWERPC_MMU_2_06:
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
2152void 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;
2178    case POWERPC_MMU_BOOKE206:
2179        /* XXX: TODO */
2180        cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
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:
2209    case POWERPC_MMU_2_06:
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)
2231void 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
2240void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
2241{
2242    LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
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        }
2263        tlb_flush(env, 1);
2264    }
2265}
2266
2267#if defined(TARGET_PPC64)
2268target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
2269{
2270    // XXX
2271    return 0;
2272}
2273#endif
2274
2275void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2276{
2277    LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2278            srnum, value, env->sr[srnum]);
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 */
2293        rs |= ((value >> 27) & 0xf) << 8;
2294
2295        ppc_store_slb(env, rb, rs);
2296    } else
2297#endif
2298    if (env->sr[srnum] != value) {
2299        env->sr[srnum] = value;
2300/* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2301   flusing the whole TLB. */
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
2312        tlb_flush(env, 1);
2313#endif
2314    }
2315}
2316#endif /* !defined (CONFIG_USER_ONLY) */
2317
2318/* GDBstub can read and write MSR... */
2319void ppc_store_msr (CPUPPCState *env, target_ulong value)
2320{
2321    hreg_store_msr(env, value, 0);
2322}
2323
2324/*****************************************************************************/
2325/* Exception processing */
2326#if defined (CONFIG_USER_ONLY)
2327void do_interrupt (CPUState *env)
2328{
2329    env->exception_index = POWERPC_EXCP_NONE;
2330    env->error_code = 0;
2331}
2332
2333void ppc_hw_interrupt (CPUState *env)
2334{
2335    env->exception_index = POWERPC_EXCP_NONE;
2336    env->error_code = 0;
2337}
2338#else /* defined (CONFIG_USER_ONLY) */
2339static inline void dump_syscall(CPUState *env)
2340{
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);
2347}
2348
2349/* Note that this function should be greatly optimized
2350 * when called with a constant excp, from ppc_hw_interrupt
2351 */
2352static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
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;
2366    }
2367
2368    qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2369                  " => %08x (%02x)\n", env->nip, excp, env->error_code);
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 */
2378    srr0 = SPR_SRR0;
2379    srr1 = SPR_SRR1;
2380    asrr0 = -1;
2381    asrr1 = -1;
2382
2383    switch (excp) {
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;
2401        }
2402        goto store_next;
2403    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
2404        if (msr_me == 0) {
2405            /* Machine check exception is not enabled.
2406             * Enter checkstop state.
2407             */
2408            if (qemu_log_enabled()) {
2409                qemu_log("Machine check while not allowed. "
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        }
2422
2423        /* machine check exceptions don't have ME set */
2424        new_msr &= ~((target_ulong)1 << MSR_ME);
2425
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;
2440        }
2441        goto store_next;
2442    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
2443        LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2444                 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2445        if (lpes1 == 0)
2446            new_msr |= (target_ulong)MSR_HVB;
2447        goto store_next;
2448    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
2449        LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2450                 "\n", msr, env->nip);
2451        if (lpes1 == 0)
2452            new_msr |= (target_ulong)MSR_HVB;
2453        msr |= env->error_code;
2454        goto store_next;
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;
2465        goto store_current;
2466    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
2467        switch (env->error_code & ~0xF) {
2468        case POWERPC_EXCP_FP:
2469            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2470                LOG_EXCP("Ignore floating point exception\n");
2471                env->exception_index = POWERPC_EXCP_NONE;
2472                env->error_code = 0;
2473                return;
2474            }
2475            if (lpes1 == 0)
2476                new_msr |= (target_ulong)MSR_HVB;
2477            msr |= 0x00100000;
2478            if (msr_fe0 == msr_fe1)
2479                goto store_next;
2480            msr |= 0x00010000;
2481            break;
2482        case POWERPC_EXCP_INVAL:
2483            LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2484            if (lpes1 == 0)
2485                new_msr |= (target_ulong)MSR_HVB;
2486            msr |= 0x00080000;
2487            break;
2488        case POWERPC_EXCP_PRIV:
2489            if (lpes1 == 0)
2490                new_msr |= (target_ulong)MSR_HVB;
2491            msr |= 0x00040000;
2492            break;
2493        case POWERPC_EXCP_TRAP:
2494            if (lpes1 == 0)
2495                new_msr |= (target_ulong)MSR_HVB;
2496            msr |= 0x00020000;
2497            break;
2498        default:
2499            /* Should never occur */
2500            cpu_abort(env, "Invalid program exception %d. Aborting\n",
2501                      env->error_code);
2502            break;
2503        }
2504        goto store_current;
2505    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
2506        if (lpes1 == 0)
2507            new_msr |= (target_ulong)MSR_HVB;
2508        goto store_current;
2509    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
2510        dump_syscall(env);
2511        lev = env->error_code;
2512        if ((lev == 1) && cpu_ppc_hypercall) {
2513            cpu_ppc_hypercall(env);
2514            return;
2515        }
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;
2524        goto store_next;
2525    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
2526        /* FIT on 4xx */
2527        LOG_EXCP("FIT exception\n");
2528        goto store_next;
2529    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
2530        LOG_EXCP("WDT exception\n");
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        }
2555        /* XXX: TODO */
2556        cpu_abort(env, "Debug exception is not implemented yet !\n");
2557        goto store_next;
2558    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
2559        goto store_current;
2560    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
2561        /* XXX: TODO */
2562        cpu_abort(env, "Embedded floating point data exception "
2563                  "is not implemented yet !\n");
2564        goto store_next;
2565    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
2566        /* XXX: TODO */
2567        cpu_abort(env, "Embedded floating point round exception "
2568                  "is not implemented yet !\n");
2569        goto store_next;
2570    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
2571        /* XXX: TODO */
2572        cpu_abort(env,
2573                  "Performance counter exception is not implemented yet !\n");
2574        goto store_next;
2575    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
2576        /* XXX: TODO */
2577        cpu_abort(env,
2578                  "Embedded doorbell interrupt is not implemented yet !\n");
2579        goto store_next;
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;
2585            break;
2586        default:
2587            break;
2588        }
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                   */
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
2601        if (0) {
2602            /* XXX: find a suitable condition to enable the hypervisor mode */
2603            new_msr |= (target_ulong)MSR_HVB;
2604        }
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;
2618        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
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;
2628        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
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;
2634        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
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;
2640        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
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;
2646        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
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    */
2653        LOG_EXCP("PIT exception\n");
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;
2681        default:
2682            cpu_abort(env, "Invalid instruction TLB miss exception\n");
2683            break;
2684        }
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;
2699        default:
2700            cpu_abort(env, "Invalid data load TLB miss exception\n");
2701            break;
2702        }
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:
2721#if defined (DEBUG_SOFTWARE_TLB)
2722            if (qemu_log_enabled()) {
2723                const char *es;
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                }
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);
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 */
2750            msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2751            break;
2752        case POWERPC_EXCP_74xx:
2753        tlb_miss_74xx:
2754#if defined (DEBUG_SOFTWARE_TLB)
2755            if (qemu_log_enabled()) {
2756                const char *es;
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                }
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);
2776            }
2777#endif
2778            msr |= env->error_code; /* key bit */
2779            break;
2780        default:
2781            cpu_abort(env, "Invalid data store TLB miss exception\n");
2782            break;
2783        }
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;
2838    default:
2839    excp_invalid:
2840        cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2841        break;
2842    store_current:
2843        /* save current instruction location */
2844        env->spr[srr0] = env->nip - 4;
2845        break;
2846    store_next:
2847        /* save next instruction location */
2848        env->spr[srr0] = env->nip;
2849        break;
2850    }
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];
2858    /* If we disactivated any translation, flush TLBs */
2859    if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2860        tlb_flush(env, 1);
2861
2862    if (msr_ile) {
2863        new_msr |= (target_ulong)1 << MSR_LE;
2864    }
2865
2866    /* Jump to handler */
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 {
2881        if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
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;
2897
2898    if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
2899        (env->mmu_model == POWERPC_MMU_BOOKE206)) {
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    }
2905}
2906
2907void do_interrupt (CPUState *env)
2908{
2909    powerpc_excp(env, env->excp_model, env->exception_index);
2910}
2911
2912void ppc_hw_interrupt (CPUPPCState *env)
2913{
2914    int hdice;
2915
2916#if 0
2917    qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
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    }
3026}
3027#endif /* !CONFIG_USER_ONLY */
3028
3029void cpu_dump_rfi (target_ulong RA, target_ulong msr)
3030{
3031    qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
3032             TARGET_FMT_lx "\n", RA, msr);
3033}
3034
3035void cpu_reset(CPUPPCState *env)
3036{
3037    target_ulong msr;
3038
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
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 */
3059    msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
3060    msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
3061    msr |= (target_ulong)1 << MSR_PR;
3062#else
3063    env->excp_prefix = env->hreset_excp_prefix;
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
3068    env->msr = msr & env->msr_mask;
3069#if defined(TARGET_PPC64)
3070    if (env->mmu_model & POWERPC_MMU_64)
3071        env->msr |= (1ULL << MSR_SF);
3072#endif
3073    hreg_compute_hflags(env);
3074    env->reserve_addr = (target_ulong)-1ULL;
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
3083CPUPPCState *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);
3094    ppc_translate_init();
3095    env->cpu_model_str = cpu_model;
3096    cpu_ppc_register_internal(env, def);
3097
3098    qemu_init_vcpu(env);
3099
3100    return env;
3101}
3102
3103void cpu_ppc_close (CPUPPCState *env)
3104{
3105    /* Should also remove all opcode tables... */
3106    qemu_free(env);
3107}
3108