qemu/target/ppc/mmu_helper.c
<<
>>
Prefs
   1/*
   2 *  PowerPC MMU, TLB, SLB and BAT 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 "qemu/osdep.h"
  20#include "qemu/units.h"
  21#include "cpu.h"
  22#include "exec/helper-proto.h"
  23#include "sysemu/kvm.h"
  24#include "kvm_ppc.h"
  25#include "mmu-hash64.h"
  26#include "mmu-hash32.h"
  27#include "exec/exec-all.h"
  28#include "exec/cpu_ldst.h"
  29#include "exec/log.h"
  30#include "helper_regs.h"
  31#include "qemu/error-report.h"
  32#include "qemu/qemu-print.h"
  33#include "mmu-book3s-v3.h"
  34#include "mmu-radix64.h"
  35
  36/* #define DEBUG_MMU */
  37/* #define DEBUG_BATS */
  38/* #define DEBUG_SOFTWARE_TLB */
  39/* #define DUMP_PAGE_TABLES */
  40/* #define FLUSH_ALL_TLBS */
  41
  42#ifdef DEBUG_MMU
  43#  define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0)
  44#else
  45#  define LOG_MMU_STATE(cpu) do { } while (0)
  46#endif
  47
  48#ifdef DEBUG_SOFTWARE_TLB
  49#  define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
  50#else
  51#  define LOG_SWTLB(...) do { } while (0)
  52#endif
  53
  54#ifdef DEBUG_BATS
  55#  define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
  56#else
  57#  define LOG_BATS(...) do { } while (0)
  58#endif
  59
  60/*****************************************************************************/
  61/* PowerPC MMU emulation */
  62
  63/* Context used internally during MMU translations */
  64typedef struct mmu_ctx_t mmu_ctx_t;
  65struct mmu_ctx_t {
  66    hwaddr raddr;      /* Real address              */
  67    hwaddr eaddr;      /* Effective address         */
  68    int prot;                      /* Protection bits           */
  69    hwaddr hash[2];    /* Pagetable hash values     */
  70    target_ulong ptem;             /* Virtual segment ID | API  */
  71    int key;                       /* Access key                */
  72    int nx;                        /* Non-execute area          */
  73};
  74
  75/* Common routines used by software and hardware TLBs emulation */
  76static inline int pte_is_valid(target_ulong pte0)
  77{
  78    return pte0 & 0x80000000 ? 1 : 0;
  79}
  80
  81static inline void pte_invalidate(target_ulong *pte0)
  82{
  83    *pte0 &= ~0x80000000;
  84}
  85
  86#define PTE_PTEM_MASK 0x7FFFFFBF
  87#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
  88
  89static int pp_check(int key, int pp, int nx)
  90{
  91    int access;
  92
  93    /* Compute access rights */
  94    access = 0;
  95    if (key == 0) {
  96        switch (pp) {
  97        case 0x0:
  98        case 0x1:
  99        case 0x2:
 100            access |= PAGE_WRITE;
 101            /* No break here */
 102        case 0x3:
 103            access |= PAGE_READ;
 104            break;
 105        }
 106    } else {
 107        switch (pp) {
 108        case 0x0:
 109            access = 0;
 110            break;
 111        case 0x1:
 112        case 0x3:
 113            access = PAGE_READ;
 114            break;
 115        case 0x2:
 116            access = PAGE_READ | PAGE_WRITE;
 117            break;
 118        }
 119    }
 120    if (nx == 0) {
 121        access |= PAGE_EXEC;
 122    }
 123
 124    return access;
 125}
 126
 127static int check_prot(int prot, int rw, int access_type)
 128{
 129    int ret;
 130
 131    if (access_type == ACCESS_CODE) {
 132        if (prot & PAGE_EXEC) {
 133            ret = 0;
 134        } else {
 135            ret = -2;
 136        }
 137    } else if (rw) {
 138        if (prot & PAGE_WRITE) {
 139            ret = 0;
 140        } else {
 141            ret = -2;
 142        }
 143    } else {
 144        if (prot & PAGE_READ) {
 145            ret = 0;
 146        } else {
 147            ret = -2;
 148        }
 149    }
 150
 151    return ret;
 152}
 153
 154static inline int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
 155                                       target_ulong pte1, int h,
 156                                       int rw, int type)
 157{
 158    target_ulong ptem, mmask;
 159    int access, ret, pteh, ptev, pp;
 160
 161    ret = -1;
 162    /* Check validity and table match */
 163    ptev = pte_is_valid(pte0);
 164    pteh = (pte0 >> 6) & 1;
 165    if (ptev && h == pteh) {
 166        /* Check vsid & api */
 167        ptem = pte0 & PTE_PTEM_MASK;
 168        mmask = PTE_CHECK_MASK;
 169        pp = pte1 & 0x00000003;
 170        if (ptem == ctx->ptem) {
 171            if (ctx->raddr != (hwaddr)-1ULL) {
 172                /* all matches should have equal RPN, WIMG & PP */
 173                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
 174                    qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
 175                    return -3;
 176                }
 177            }
 178            /* Compute access rights */
 179            access = pp_check(ctx->key, pp, ctx->nx);
 180            /* Keep the matching PTE informations */
 181            ctx->raddr = pte1;
 182            ctx->prot = access;
 183            ret = check_prot(ctx->prot, rw, type);
 184            if (ret == 0) {
 185                /* Access granted */
 186                qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
 187            } else {
 188                /* Access right violation */
 189                qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
 190            }
 191        }
 192    }
 193
 194    return ret;
 195}
 196
 197static int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
 198                            int ret, int rw)
 199{
 200    int store = 0;
 201
 202    /* Update page flags */
 203    if (!(*pte1p & 0x00000100)) {
 204        /* Update accessed flag */
 205        *pte1p |= 0x00000100;
 206        store = 1;
 207    }
 208    if (!(*pte1p & 0x00000080)) {
 209        if (rw == 1 && ret == 0) {
 210            /* Update changed flag */
 211            *pte1p |= 0x00000080;
 212            store = 1;
 213        } else {
 214            /* Force page fault for first write access */
 215            ctx->prot &= ~PAGE_WRITE;
 216        }
 217    }
 218
 219    return store;
 220}
 221
 222/* Software driven TLB helpers */
 223static inline int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 224                                    int way, int is_code)
 225{
 226    int nr;
 227
 228    /* Select TLB num in a way from address */
 229    nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
 230    /* Select TLB way */
 231    nr += env->tlb_per_way * way;
 232    /* 6xx have separate TLBs for instructions and data */
 233    if (is_code && env->id_tlbs == 1) {
 234        nr += env->nb_tlb;
 235    }
 236
 237    return nr;
 238}
 239
 240static inline void ppc6xx_tlb_invalidate_all(CPUPPCState *env)
 241{
 242    ppc6xx_tlb_t *tlb;
 243    int nr, max;
 244
 245    /* LOG_SWTLB("Invalidate all TLBs\n"); */
 246    /* Invalidate all defined software TLB */
 247    max = env->nb_tlb;
 248    if (env->id_tlbs == 1) {
 249        max *= 2;
 250    }
 251    for (nr = 0; nr < max; nr++) {
 252        tlb = &env->tlb.tlb6[nr];
 253        pte_invalidate(&tlb->pte0);
 254    }
 255    tlb_flush(env_cpu(env));
 256}
 257
 258static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState *env,
 259                                               target_ulong eaddr,
 260                                               int is_code, int match_epn)
 261{
 262#if !defined(FLUSH_ALL_TLBS)
 263    CPUState *cs = env_cpu(env);
 264    ppc6xx_tlb_t *tlb;
 265    int way, nr;
 266
 267    /* Invalidate ITLB + DTLB, all ways */
 268    for (way = 0; way < env->nb_ways; way++) {
 269        nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
 270        tlb = &env->tlb.tlb6[nr];
 271        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
 272            LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
 273                      env->nb_tlb, eaddr);
 274            pte_invalidate(&tlb->pte0);
 275            tlb_flush_page(cs, tlb->EPN);
 276        }
 277    }
 278#else
 279    /* XXX: PowerPC specification say this is valid as well */
 280    ppc6xx_tlb_invalidate_all(env);
 281#endif
 282}
 283
 284static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState *env,
 285                                              target_ulong eaddr, int is_code)
 286{
 287    ppc6xx_tlb_invalidate_virt2(env, eaddr, is_code, 0);
 288}
 289
 290static void ppc6xx_tlb_store(CPUPPCState *env, target_ulong EPN, int way,
 291                             int is_code, target_ulong pte0, target_ulong pte1)
 292{
 293    ppc6xx_tlb_t *tlb;
 294    int nr;
 295
 296    nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
 297    tlb = &env->tlb.tlb6[nr];
 298    LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
 299              " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
 300    /* Invalidate any pending reference in QEMU for this virtual address */
 301    ppc6xx_tlb_invalidate_virt2(env, EPN, is_code, 1);
 302    tlb->pte0 = pte0;
 303    tlb->pte1 = pte1;
 304    tlb->EPN = EPN;
 305    /* Store last way for LRU mechanism */
 306    env->last_way = way;
 307}
 308
 309static inline int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
 310                                   target_ulong eaddr, int rw, int access_type)
 311{
 312    ppc6xx_tlb_t *tlb;
 313    int nr, best, way;
 314    int ret;
 315
 316    best = -1;
 317    ret = -1; /* No TLB found */
 318    for (way = 0; way < env->nb_ways; way++) {
 319        nr = ppc6xx_tlb_getnum(env, eaddr, way,
 320                               access_type == ACCESS_CODE ? 1 : 0);
 321        tlb = &env->tlb.tlb6[nr];
 322        /* This test "emulates" the PTE index match for hardware TLBs */
 323        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
 324            LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
 325                      "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
 326                      pte_is_valid(tlb->pte0) ? "valid" : "inval",
 327                      tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
 328            continue;
 329        }
 330        LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
 331                  TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
 332                  pte_is_valid(tlb->pte0) ? "valid" : "inval",
 333                  tlb->EPN, eaddr, tlb->pte1,
 334                  rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
 335        switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1,
 336                                     0, rw, access_type)) {
 337        case -3:
 338            /* TLB inconsistency */
 339            return -1;
 340        case -2:
 341            /* Access violation */
 342            ret = -2;
 343            best = nr;
 344            break;
 345        case -1:
 346        default:
 347            /* No match */
 348            break;
 349        case 0:
 350            /* access granted */
 351            /*
 352             * XXX: we should go on looping to check all TLBs
 353             *      consistency but we can speed-up the whole thing as
 354             *      the result would be undefined if TLBs are not
 355             *      consistent.
 356             */
 357            ret = 0;
 358            best = nr;
 359            goto done;
 360        }
 361    }
 362    if (best != -1) {
 363    done:
 364        LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
 365                  ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
 366        /* Update page flags */
 367        pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, rw);
 368    }
 369
 370    return ret;
 371}
 372
 373/* Perform BAT hit & translation */
 374static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
 375                                 int *validp, int *protp, target_ulong *BATu,
 376                                 target_ulong *BATl)
 377{
 378    target_ulong bl;
 379    int pp, valid, prot;
 380
 381    bl = (*BATu & 0x00001FFC) << 15;
 382    valid = 0;
 383    prot = 0;
 384    if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
 385        ((msr_pr != 0) && (*BATu & 0x00000001))) {
 386        valid = 1;
 387        pp = *BATl & 0x00000003;
 388        if (pp != 0) {
 389            prot = PAGE_READ | PAGE_EXEC;
 390            if (pp == 0x2) {
 391                prot |= PAGE_WRITE;
 392            }
 393        }
 394    }
 395    *blp = bl;
 396    *validp = valid;
 397    *protp = prot;
 398}
 399
 400static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
 401                           target_ulong virtual, int rw, int type)
 402{
 403    target_ulong *BATlt, *BATut, *BATu, *BATl;
 404    target_ulong BEPIl, BEPIu, bl;
 405    int i, valid, prot;
 406    int ret = -1;
 407
 408    LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
 409             type == ACCESS_CODE ? 'I' : 'D', virtual);
 410    switch (type) {
 411    case ACCESS_CODE:
 412        BATlt = env->IBAT[1];
 413        BATut = env->IBAT[0];
 414        break;
 415    default:
 416        BATlt = env->DBAT[1];
 417        BATut = env->DBAT[0];
 418        break;
 419    }
 420    for (i = 0; i < env->nb_BATs; i++) {
 421        BATu = &BATut[i];
 422        BATl = &BATlt[i];
 423        BEPIu = *BATu & 0xF0000000;
 424        BEPIl = *BATu & 0x0FFE0000;
 425        bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
 426        LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
 427                 " BATl " TARGET_FMT_lx "\n", __func__,
 428                 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
 429        if ((virtual & 0xF0000000) == BEPIu &&
 430            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
 431            /* BAT matches */
 432            if (valid != 0) {
 433                /* Get physical address */
 434                ctx->raddr = (*BATl & 0xF0000000) |
 435                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
 436                    (virtual & 0x0001F000);
 437                /* Compute access rights */
 438                ctx->prot = prot;
 439                ret = check_prot(ctx->prot, rw, type);
 440                if (ret == 0) {
 441                    LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
 442                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
 443                             ctx->prot & PAGE_WRITE ? 'W' : '-');
 444                }
 445                break;
 446            }
 447        }
 448    }
 449    if (ret < 0) {
 450#if defined(DEBUG_BATS)
 451        if (qemu_log_enabled()) {
 452            LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
 453            for (i = 0; i < 4; i++) {
 454                BATu = &BATut[i];
 455                BATl = &BATlt[i];
 456                BEPIu = *BATu & 0xF0000000;
 457                BEPIl = *BATu & 0x0FFE0000;
 458                bl = (*BATu & 0x00001FFC) << 15;
 459                LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
 460                         " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
 461                         TARGET_FMT_lx " " TARGET_FMT_lx "\n",
 462                         __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
 463                         *BATu, *BATl, BEPIu, BEPIl, bl);
 464            }
 465        }
 466#endif
 467    }
 468    /* No hit */
 469    return ret;
 470}
 471
 472/* Perform segment based translation */
 473static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
 474                                      target_ulong eaddr, int rw, int type)
 475{
 476    PowerPCCPU *cpu = env_archcpu(env);
 477    hwaddr hash;
 478    target_ulong vsid;
 479    int ds, pr, target_page_bits;
 480    int ret;
 481    target_ulong sr, pgidx;
 482
 483    pr = msr_pr;
 484    ctx->eaddr = eaddr;
 485
 486    sr = env->sr[eaddr >> 28];
 487    ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
 488                ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
 489    ds = sr & 0x80000000 ? 1 : 0;
 490    ctx->nx = sr & 0x10000000 ? 1 : 0;
 491    vsid = sr & 0x00FFFFFF;
 492    target_page_bits = TARGET_PAGE_BITS;
 493    qemu_log_mask(CPU_LOG_MMU,
 494            "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
 495            " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
 496            " ir=%d dr=%d pr=%d %d t=%d\n",
 497            eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
 498            (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
 499    pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
 500    hash = vsid ^ pgidx;
 501    ctx->ptem = (vsid << 7) | (pgidx >> 10);
 502
 503    qemu_log_mask(CPU_LOG_MMU,
 504            "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
 505            ctx->key, ds, ctx->nx, vsid);
 506    ret = -1;
 507    if (!ds) {
 508        /* Check if instruction fetch is allowed, if needed */
 509        if (type != ACCESS_CODE || ctx->nx == 0) {
 510            /* Page address translation */
 511            qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx
 512                    " htab_mask " TARGET_FMT_plx
 513                    " hash " TARGET_FMT_plx "\n",
 514                    ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
 515            ctx->hash[0] = hash;
 516            ctx->hash[1] = ~hash;
 517
 518            /* Initialize real address with an invalid value */
 519            ctx->raddr = (hwaddr)-1ULL;
 520            /* Software TLB search */
 521            ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
 522#if defined(DUMP_PAGE_TABLES)
 523            if (qemu_loglevel_mask(CPU_LOG_MMU)) {
 524                CPUState *cs = env_cpu(env);
 525                hwaddr curaddr;
 526                uint32_t a0, a1, a2, a3;
 527
 528                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
 529                         "\n", ppc_hash32_hpt_base(cpu),
 530                         ppc_hash32_hpt_mask(env) + 0x80);
 531                for (curaddr = ppc_hash32_hpt_base(cpu);
 532                     curaddr < (ppc_hash32_hpt_base(cpu)
 533                                + ppc_hash32_hpt_mask(cpu) + 0x80);
 534                     curaddr += 16) {
 535                    a0 = ldl_phys(cs->as, curaddr);
 536                    a1 = ldl_phys(cs->as, curaddr + 4);
 537                    a2 = ldl_phys(cs->as, curaddr + 8);
 538                    a3 = ldl_phys(cs->as, curaddr + 12);
 539                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
 540                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
 541                                 curaddr, a0, a1, a2, a3);
 542                    }
 543                }
 544            }
 545#endif
 546        } else {
 547            qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
 548            ret = -3;
 549        }
 550    } else {
 551        target_ulong sr;
 552
 553        qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
 554        /* Direct-store segment : absolutely *BUGGY* for now */
 555
 556        /*
 557         * Direct-store implies a 32-bit MMU.
 558         * Check the Segment Register's bus unit ID (BUID).
 559         */
 560        sr = env->sr[eaddr >> 28];
 561        if ((sr & 0x1FF00000) >> 20 == 0x07f) {
 562            /*
 563             * Memory-forced I/O controller interface access
 564             *
 565             * If T=1 and BUID=x'07F', the 601 performs a memory
 566             * access to SR[28-31] LA[4-31], bypassing all protection
 567             * mechanisms.
 568             */
 569            ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
 570            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 571            return 0;
 572        }
 573
 574        switch (type) {
 575        case ACCESS_INT:
 576            /* Integer load/store : only access allowed */
 577            break;
 578        case ACCESS_CODE:
 579            /* No code fetch is allowed in direct-store areas */
 580            return -4;
 581        case ACCESS_FLOAT:
 582            /* Floating point load/store */
 583            return -4;
 584        case ACCESS_RES:
 585            /* lwarx, ldarx or srwcx. */
 586            return -4;
 587        case ACCESS_CACHE:
 588            /*
 589             * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
 590             *
 591             * Should make the instruction do no-op.  As it already do
 592             * no-op, it's quite easy :-)
 593             */
 594            ctx->raddr = eaddr;
 595            return 0;
 596        case ACCESS_EXT:
 597            /* eciwx or ecowx */
 598            return -4;
 599        default:
 600            qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need "
 601                          "address translation\n");
 602            return -4;
 603        }
 604        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
 605            ctx->raddr = eaddr;
 606            ret = 2;
 607        } else {
 608            ret = -2;
 609        }
 610    }
 611
 612    return ret;
 613}
 614
 615/* Generic TLB check function for embedded PowerPC implementations */
 616static int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
 617                            hwaddr *raddrp,
 618                            target_ulong address, uint32_t pid, int ext,
 619                            int i)
 620{
 621    target_ulong mask;
 622
 623    /* Check valid flag */
 624    if (!(tlb->prot & PAGE_VALID)) {
 625        return -1;
 626    }
 627    mask = ~(tlb->size - 1);
 628    LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
 629              " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
 630              mask, (uint32_t)tlb->PID, tlb->prot);
 631    /* Check PID */
 632    if (tlb->PID != 0 && tlb->PID != pid) {
 633        return -1;
 634    }
 635    /* Check effective address */
 636    if ((address & mask) != tlb->EPN) {
 637        return -1;
 638    }
 639    *raddrp = (tlb->RPN & mask) | (address & ~mask);
 640    if (ext) {
 641        /* Extend the physical address to 36 bits */
 642        *raddrp |= (uint64_t)(tlb->RPN & 0xF) << 32;
 643    }
 644
 645    return 0;
 646}
 647
 648/* Generic TLB search function for PowerPC embedded implementations */
 649static int ppcemb_tlb_search(CPUPPCState *env, target_ulong address,
 650                             uint32_t pid)
 651{
 652    ppcemb_tlb_t *tlb;
 653    hwaddr raddr;
 654    int i, ret;
 655
 656    /* Default return value is no match */
 657    ret = -1;
 658    for (i = 0; i < env->nb_tlb; i++) {
 659        tlb = &env->tlb.tlbe[i];
 660        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
 661            ret = i;
 662            break;
 663        }
 664    }
 665
 666    return ret;
 667}
 668
 669/* Helpers specific to PowerPC 40x implementations */
 670static inline void ppc4xx_tlb_invalidate_all(CPUPPCState *env)
 671{
 672    ppcemb_tlb_t *tlb;
 673    int i;
 674
 675    for (i = 0; i < env->nb_tlb; i++) {
 676        tlb = &env->tlb.tlbe[i];
 677        tlb->prot &= ~PAGE_VALID;
 678    }
 679    tlb_flush(env_cpu(env));
 680}
 681
 682static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
 683                                       target_ulong address, int rw,
 684                                       int access_type)
 685{
 686    ppcemb_tlb_t *tlb;
 687    hwaddr raddr;
 688    int i, ret, zsel, zpr, pr;
 689
 690    ret = -1;
 691    raddr = (hwaddr)-1ULL;
 692    pr = msr_pr;
 693    for (i = 0; i < env->nb_tlb; i++) {
 694        tlb = &env->tlb.tlbe[i];
 695        if (ppcemb_tlb_check(env, tlb, &raddr, address,
 696                             env->spr[SPR_40x_PID], 0, i) < 0) {
 697            continue;
 698        }
 699        zsel = (tlb->attr >> 4) & 0xF;
 700        zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
 701        LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
 702                    __func__, i, zsel, zpr, rw, tlb->attr);
 703        /* Check execute enable bit */
 704        switch (zpr) {
 705        case 0x2:
 706            if (pr != 0) {
 707                goto check_perms;
 708            }
 709            /* No break here */
 710        case 0x3:
 711            /* All accesses granted */
 712            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 713            ret = 0;
 714            break;
 715        case 0x0:
 716            if (pr != 0) {
 717                /* Raise Zone protection fault.  */
 718                env->spr[SPR_40x_ESR] = 1 << 22;
 719                ctx->prot = 0;
 720                ret = -2;
 721                break;
 722            }
 723            /* No break here */
 724        case 0x1:
 725        check_perms:
 726            /* Check from TLB entry */
 727            ctx->prot = tlb->prot;
 728            ret = check_prot(ctx->prot, rw, access_type);
 729            if (ret == -2) {
 730                env->spr[SPR_40x_ESR] = 0;
 731            }
 732            break;
 733        }
 734        if (ret >= 0) {
 735            ctx->raddr = raddr;
 736            LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
 737                      " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
 738                      ret);
 739            return 0;
 740        }
 741    }
 742    LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
 743              " %d %d\n", __func__, address, raddr, ctx->prot, ret);
 744
 745    return ret;
 746}
 747
 748void store_40x_sler(CPUPPCState *env, uint32_t val)
 749{
 750    /* XXX: TO BE FIXED */
 751    if (val != 0x00000000) {
 752        cpu_abort(env_cpu(env),
 753                  "Little-endian regions are not supported by now\n");
 754    }
 755    env->spr[SPR_405_SLER] = val;
 756}
 757
 758static inline int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb,
 759                                     hwaddr *raddr, int *prot,
 760                                     target_ulong address, int rw,
 761                                     int access_type, int i)
 762{
 763    int ret, prot2;
 764
 765    if (ppcemb_tlb_check(env, tlb, raddr, address,
 766                         env->spr[SPR_BOOKE_PID],
 767                         !env->nb_pids, i) >= 0) {
 768        goto found_tlb;
 769    }
 770
 771    if (env->spr[SPR_BOOKE_PID1] &&
 772        ppcemb_tlb_check(env, tlb, raddr, address,
 773                         env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
 774        goto found_tlb;
 775    }
 776
 777    if (env->spr[SPR_BOOKE_PID2] &&
 778        ppcemb_tlb_check(env, tlb, raddr, address,
 779                         env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
 780        goto found_tlb;
 781    }
 782
 783    LOG_SWTLB("%s: TLB entry not found\n", __func__);
 784    return -1;
 785
 786found_tlb:
 787
 788    if (msr_pr != 0) {
 789        prot2 = tlb->prot & 0xF;
 790    } else {
 791        prot2 = (tlb->prot >> 4) & 0xF;
 792    }
 793
 794    /* Check the address space */
 795    if (access_type == ACCESS_CODE) {
 796        if (msr_ir != (tlb->attr & 1)) {
 797            LOG_SWTLB("%s: AS doesn't match\n", __func__);
 798            return -1;
 799        }
 800
 801        *prot = prot2;
 802        if (prot2 & PAGE_EXEC) {
 803            LOG_SWTLB("%s: good TLB!\n", __func__);
 804            return 0;
 805        }
 806
 807        LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, prot2);
 808        ret = -3;
 809    } else {
 810        if (msr_dr != (tlb->attr & 1)) {
 811            LOG_SWTLB("%s: AS doesn't match\n", __func__);
 812            return -1;
 813        }
 814
 815        *prot = prot2;
 816        if ((!rw && prot2 & PAGE_READ) || (rw && (prot2 & PAGE_WRITE))) {
 817            LOG_SWTLB("%s: found TLB!\n", __func__);
 818            return 0;
 819        }
 820
 821        LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, prot2);
 822        ret = -2;
 823    }
 824
 825    return ret;
 826}
 827
 828static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
 829                                         target_ulong address, int rw,
 830                                         int access_type)
 831{
 832    ppcemb_tlb_t *tlb;
 833    hwaddr raddr;
 834    int i, ret;
 835
 836    ret = -1;
 837    raddr = (hwaddr)-1ULL;
 838    for (i = 0; i < env->nb_tlb; i++) {
 839        tlb = &env->tlb.tlbe[i];
 840        ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
 841                                 access_type, i);
 842        if (ret != -1) {
 843            break;
 844        }
 845    }
 846
 847    if (ret >= 0) {
 848        ctx->raddr = raddr;
 849        LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
 850                  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
 851                  ret);
 852    } else {
 853        LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
 854                  " %d %d\n", __func__, address, raddr, ctx->prot, ret);
 855    }
 856
 857    return ret;
 858}
 859
 860static void booke206_flush_tlb(CPUPPCState *env, int flags,
 861                               const int check_iprot)
 862{
 863    int tlb_size;
 864    int i, j;
 865    ppcmas_tlb_t *tlb = env->tlb.tlbm;
 866
 867    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
 868        if (flags & (1 << i)) {
 869            tlb_size = booke206_tlb_size(env, i);
 870            for (j = 0; j < tlb_size; j++) {
 871                if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) {
 872                    tlb[j].mas1 &= ~MAS1_VALID;
 873                }
 874            }
 875        }
 876        tlb += booke206_tlb_size(env, i);
 877    }
 878
 879    tlb_flush(env_cpu(env));
 880}
 881
 882static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
 883                                        ppcmas_tlb_t *tlb)
 884{
 885    int tlbm_size;
 886
 887    tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
 888
 889    return 1024ULL << tlbm_size;
 890}
 891
 892/* TLB check function for MAS based SoftTLBs */
 893static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
 894                            hwaddr *raddrp, target_ulong address,
 895                            uint32_t pid)
 896{
 897    hwaddr mask;
 898    uint32_t tlb_pid;
 899
 900    if (!msr_cm) {
 901        /* In 32bit mode we can only address 32bit EAs */
 902        address = (uint32_t)address;
 903    }
 904
 905    /* Check valid flag */
 906    if (!(tlb->mas1 & MAS1_VALID)) {
 907        return -1;
 908    }
 909
 910    mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
 911    LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
 912              PRIx64 " mask=0x%" HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%"
 913              PRIx32 "\n", __func__, address, pid, tlb->mas1, tlb->mas2, mask,
 914              tlb->mas7_3, tlb->mas8);
 915
 916    /* Check PID */
 917    tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
 918    if (tlb_pid != 0 && tlb_pid != pid) {
 919        return -1;
 920    }
 921
 922    /* Check effective address */
 923    if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
 924        return -1;
 925    }
 926
 927    if (raddrp) {
 928        *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
 929    }
 930
 931    return 0;
 932}
 933
 934static bool is_epid_mmu(int mmu_idx)
 935{
 936    return mmu_idx == PPC_TLB_EPID_STORE || mmu_idx == PPC_TLB_EPID_LOAD;
 937}
 938
 939static uint32_t mmubooke206_esr(int mmu_idx, bool rw)
 940{
 941    uint32_t esr = 0;
 942    if (rw) {
 943        esr |= ESR_ST;
 944    }
 945    if (is_epid_mmu(mmu_idx)) {
 946        esr |= ESR_EPID;
 947    }
 948    return esr;
 949}
 950
 951/*
 952 * Get EPID register given the mmu_idx. If this is regular load,
 953 * construct the EPID access bits from current processor state
 954 *
 955 * Get the effective AS and PR bits and the PID. The PID is returned
 956 * only if EPID load is requested, otherwise the caller must detect
 957 * the correct EPID.  Return true if valid EPID is returned.
 958 */
 959static bool mmubooke206_get_as(CPUPPCState *env,
 960                               int mmu_idx, uint32_t *epid_out,
 961                               bool *as_out, bool *pr_out)
 962{
 963    if (is_epid_mmu(mmu_idx)) {
 964        uint32_t epidr;
 965        if (mmu_idx == PPC_TLB_EPID_STORE) {
 966            epidr = env->spr[SPR_BOOKE_EPSC];
 967        } else {
 968            epidr = env->spr[SPR_BOOKE_EPLC];
 969        }
 970        *epid_out = (epidr & EPID_EPID) >> EPID_EPID_SHIFT;
 971        *as_out = !!(epidr & EPID_EAS);
 972        *pr_out = !!(epidr & EPID_EPR);
 973        return true;
 974    } else {
 975        *as_out = msr_ds;
 976        *pr_out = msr_pr;
 977        return false;
 978    }
 979}
 980
 981/* Check if the tlb found by hashing really matches */
 982static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
 983                                 hwaddr *raddr, int *prot,
 984                                 target_ulong address, int rw,
 985                                 int access_type, int mmu_idx)
 986{
 987    int ret;
 988    int prot2 = 0;
 989    uint32_t epid;
 990    bool as, pr;
 991    bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
 992
 993    if (!use_epid) {
 994        if (ppcmas_tlb_check(env, tlb, raddr, address,
 995                             env->spr[SPR_BOOKE_PID]) >= 0) {
 996            goto found_tlb;
 997        }
 998
 999        if (env->spr[SPR_BOOKE_PID1] &&
1000            ppcmas_tlb_check(env, tlb, raddr, address,
1001                             env->spr[SPR_BOOKE_PID1]) >= 0) {
1002            goto found_tlb;
1003        }
1004
1005        if (env->spr[SPR_BOOKE_PID2] &&
1006            ppcmas_tlb_check(env, tlb, raddr, address,
1007                             env->spr[SPR_BOOKE_PID2]) >= 0) {
1008            goto found_tlb;
1009        }
1010    } else {
1011        if (ppcmas_tlb_check(env, tlb, raddr, address, epid) >= 0) {
1012            goto found_tlb;
1013        }
1014    }
1015
1016    LOG_SWTLB("%s: TLB entry not found\n", __func__);
1017    return -1;
1018
1019found_tlb:
1020
1021    if (pr) {
1022        if (tlb->mas7_3 & MAS3_UR) {
1023            prot2 |= PAGE_READ;
1024        }
1025        if (tlb->mas7_3 & MAS3_UW) {
1026            prot2 |= PAGE_WRITE;
1027        }
1028        if (tlb->mas7_3 & MAS3_UX) {
1029            prot2 |= PAGE_EXEC;
1030        }
1031    } else {
1032        if (tlb->mas7_3 & MAS3_SR) {
1033            prot2 |= PAGE_READ;
1034        }
1035        if (tlb->mas7_3 & MAS3_SW) {
1036            prot2 |= PAGE_WRITE;
1037        }
1038        if (tlb->mas7_3 & MAS3_SX) {
1039            prot2 |= PAGE_EXEC;
1040        }
1041    }
1042
1043    /* Check the address space and permissions */
1044    if (access_type == ACCESS_CODE) {
1045        /* There is no way to fetch code using epid load */
1046        assert(!use_epid);
1047        if (msr_ir != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1048            LOG_SWTLB("%s: AS doesn't match\n", __func__);
1049            return -1;
1050        }
1051
1052        *prot = prot2;
1053        if (prot2 & PAGE_EXEC) {
1054            LOG_SWTLB("%s: good TLB!\n", __func__);
1055            return 0;
1056        }
1057
1058        LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, prot2);
1059        ret = -3;
1060    } else {
1061        if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1062            LOG_SWTLB("%s: AS doesn't match\n", __func__);
1063            return -1;
1064        }
1065
1066        *prot = prot2;
1067        if ((!rw && prot2 & PAGE_READ) || (rw && (prot2 & PAGE_WRITE))) {
1068            LOG_SWTLB("%s: found TLB!\n", __func__);
1069            return 0;
1070        }
1071
1072        LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, prot2);
1073        ret = -2;
1074    }
1075
1076    return ret;
1077}
1078
1079static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
1080                                            target_ulong address, int rw,
1081                                            int access_type, int mmu_idx)
1082{
1083    ppcmas_tlb_t *tlb;
1084    hwaddr raddr;
1085    int i, j, ret;
1086
1087    ret = -1;
1088    raddr = (hwaddr)-1ULL;
1089
1090    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1091        int ways = booke206_tlb_ways(env, i);
1092
1093        for (j = 0; j < ways; j++) {
1094            tlb = booke206_get_tlbm(env, i, address, j);
1095            if (!tlb) {
1096                continue;
1097            }
1098            ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
1099                                        rw, access_type, mmu_idx);
1100            if (ret != -1) {
1101                goto found_tlb;
1102            }
1103        }
1104    }
1105
1106found_tlb:
1107
1108    if (ret >= 0) {
1109        ctx->raddr = raddr;
1110        LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1111                  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1112                  ret);
1113    } else {
1114        LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1115                  " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1116    }
1117
1118    return ret;
1119}
1120
1121static const char *book3e_tsize_to_str[32] = {
1122    "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1123    "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1124    "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1125    "1T", "2T"
1126};
1127
1128static void mmubooke_dump_mmu(CPUPPCState *env)
1129{
1130    ppcemb_tlb_t *entry;
1131    int i;
1132
1133    if (kvm_enabled() && !env->kvm_sw_tlb) {
1134        qemu_printf("Cannot access KVM TLB\n");
1135        return;
1136    }
1137
1138    qemu_printf("\nTLB:\n");
1139    qemu_printf("Effective          Physical           Size PID   Prot     "
1140                "Attr\n");
1141
1142    entry = &env->tlb.tlbe[0];
1143    for (i = 0; i < env->nb_tlb; i++, entry++) {
1144        hwaddr ea, pa;
1145        target_ulong mask;
1146        uint64_t size = (uint64_t)entry->size;
1147        char size_buf[20];
1148
1149        /* Check valid flag */
1150        if (!(entry->prot & PAGE_VALID)) {
1151            continue;
1152        }
1153
1154        mask = ~(entry->size - 1);
1155        ea = entry->EPN & mask;
1156        pa = entry->RPN & mask;
1157        /* Extend the physical address to 36 bits */
1158        pa |= (hwaddr)(entry->RPN & 0xF) << 32;
1159        if (size >= 1 * MiB) {
1160            snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB);
1161        } else {
1162            snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB);
1163        }
1164        qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
1165                    (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
1166                    entry->prot, entry->attr);
1167    }
1168
1169}
1170
1171static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset,
1172                                     int tlbsize)
1173{
1174    ppcmas_tlb_t *entry;
1175    int i;
1176
1177    qemu_printf("\nTLB%d:\n", tlbn);
1178    qemu_printf("Effective          Physical           Size TID   TS SRWX"
1179                " URWX WIMGE U0123\n");
1180
1181    entry = &env->tlb.tlbm[offset];
1182    for (i = 0; i < tlbsize; i++, entry++) {
1183        hwaddr ea, pa, size;
1184        int tsize;
1185
1186        if (!(entry->mas1 & MAS1_VALID)) {
1187            continue;
1188        }
1189
1190        tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1191        size = 1024ULL << tsize;
1192        ea = entry->mas2 & ~(size - 1);
1193        pa = entry->mas7_3 & ~(size - 1);
1194
1195        qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u  S%c%c%c"
1196                    "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1197                    (uint64_t)ea, (uint64_t)pa,
1198                    book3e_tsize_to_str[tsize],
1199                    (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
1200                    (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
1201                    entry->mas7_3 & MAS3_SR ? 'R' : '-',
1202                    entry->mas7_3 & MAS3_SW ? 'W' : '-',
1203                    entry->mas7_3 & MAS3_SX ? 'X' : '-',
1204                    entry->mas7_3 & MAS3_UR ? 'R' : '-',
1205                    entry->mas7_3 & MAS3_UW ? 'W' : '-',
1206                    entry->mas7_3 & MAS3_UX ? 'X' : '-',
1207                    entry->mas2 & MAS2_W ? 'W' : '-',
1208                    entry->mas2 & MAS2_I ? 'I' : '-',
1209                    entry->mas2 & MAS2_M ? 'M' : '-',
1210                    entry->mas2 & MAS2_G ? 'G' : '-',
1211                    entry->mas2 & MAS2_E ? 'E' : '-',
1212                    entry->mas7_3 & MAS3_U0 ? '0' : '-',
1213                    entry->mas7_3 & MAS3_U1 ? '1' : '-',
1214                    entry->mas7_3 & MAS3_U2 ? '2' : '-',
1215                    entry->mas7_3 & MAS3_U3 ? '3' : '-');
1216    }
1217}
1218
1219static void mmubooke206_dump_mmu(CPUPPCState *env)
1220{
1221    int offset = 0;
1222    int i;
1223
1224    if (kvm_enabled() && !env->kvm_sw_tlb) {
1225        qemu_printf("Cannot access KVM TLB\n");
1226        return;
1227    }
1228
1229    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1230        int size = booke206_tlb_size(env, i);
1231
1232        if (size == 0) {
1233            continue;
1234        }
1235
1236        mmubooke206_dump_one_tlb(env, i, offset, size);
1237        offset += size;
1238    }
1239}
1240
1241static void mmu6xx_dump_BATs(CPUPPCState *env, int type)
1242{
1243    target_ulong *BATlt, *BATut, *BATu, *BATl;
1244    target_ulong BEPIl, BEPIu, bl;
1245    int i;
1246
1247    switch (type) {
1248    case ACCESS_CODE:
1249        BATlt = env->IBAT[1];
1250        BATut = env->IBAT[0];
1251        break;
1252    default:
1253        BATlt = env->DBAT[1];
1254        BATut = env->DBAT[0];
1255        break;
1256    }
1257
1258    for (i = 0; i < env->nb_BATs; i++) {
1259        BATu = &BATut[i];
1260        BATl = &BATlt[i];
1261        BEPIu = *BATu & 0xF0000000;
1262        BEPIl = *BATu & 0x0FFE0000;
1263        bl = (*BATu & 0x00001FFC) << 15;
1264        qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
1265                    " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
1266                    TARGET_FMT_lx " " TARGET_FMT_lx "\n",
1267                    type == ACCESS_CODE ? "code" : "data", i,
1268                    *BATu, *BATl, BEPIu, BEPIl, bl);
1269    }
1270}
1271
1272static void mmu6xx_dump_mmu(CPUPPCState *env)
1273{
1274    PowerPCCPU *cpu = env_archcpu(env);
1275    ppc6xx_tlb_t *tlb;
1276    target_ulong sr;
1277    int type, way, entry, i;
1278
1279    qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu));
1280    qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu));
1281
1282    qemu_printf("\nSegment registers:\n");
1283    for (i = 0; i < 32; i++) {
1284        sr = env->sr[i];
1285        if (sr & 0x80000000) {
1286            qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1287                        "CNTLR_SPEC=0x%05x\n", i,
1288                        sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
1289                        sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF),
1290                        (uint32_t)(sr & 0xFFFFF));
1291        } else {
1292            qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i,
1293                        sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
1294                        sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0,
1295                        (uint32_t)(sr & 0x00FFFFFF));
1296        }
1297    }
1298
1299    qemu_printf("\nBATs:\n");
1300    mmu6xx_dump_BATs(env, ACCESS_INT);
1301    mmu6xx_dump_BATs(env, ACCESS_CODE);
1302
1303    if (env->id_tlbs != 1) {
1304        qemu_printf("ERROR: 6xx MMU should have separated TLB"
1305                    " for code and data\n");
1306    }
1307
1308    qemu_printf("\nTLBs                       [EPN    EPN + SIZE]\n");
1309
1310    for (type = 0; type < 2; type++) {
1311        for (way = 0; way < env->nb_ways; way++) {
1312            for (entry = env->nb_tlb * type + env->tlb_per_way * way;
1313                 entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1));
1314                 entry++) {
1315
1316                tlb = &env->tlb.tlb6[entry];
1317                qemu_printf("%s TLB %02d/%02d way:%d %s ["
1318                            TARGET_FMT_lx " " TARGET_FMT_lx "]\n",
1319                            type ? "code" : "data", entry % env->nb_tlb,
1320                            env->nb_tlb, way,
1321                            pte_is_valid(tlb->pte0) ? "valid" : "inval",
1322                            tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE);
1323            }
1324        }
1325    }
1326}
1327
1328void dump_mmu(CPUPPCState *env)
1329{
1330    switch (env->mmu_model) {
1331    case POWERPC_MMU_BOOKE:
1332        mmubooke_dump_mmu(env);
1333        break;
1334    case POWERPC_MMU_BOOKE206:
1335        mmubooke206_dump_mmu(env);
1336        break;
1337    case POWERPC_MMU_SOFT_6xx:
1338    case POWERPC_MMU_SOFT_74xx:
1339        mmu6xx_dump_mmu(env);
1340        break;
1341#if defined(TARGET_PPC64)
1342    case POWERPC_MMU_64B:
1343    case POWERPC_MMU_2_03:
1344    case POWERPC_MMU_2_06:
1345    case POWERPC_MMU_2_07:
1346        dump_slb(env_archcpu(env));
1347        break;
1348    case POWERPC_MMU_3_00:
1349        if (ppc64_v3_radix(env_archcpu(env))) {
1350            /* TODO - Unsupported */
1351        } else {
1352            dump_slb(env_archcpu(env));
1353            break;
1354        }
1355#endif
1356    default:
1357        qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
1358    }
1359}
1360
1361static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
1362                                 target_ulong eaddr, int rw)
1363{
1364    int in_plb, ret;
1365
1366    ctx->raddr = eaddr;
1367    ctx->prot = PAGE_READ | PAGE_EXEC;
1368    ret = 0;
1369    switch (env->mmu_model) {
1370    case POWERPC_MMU_SOFT_6xx:
1371    case POWERPC_MMU_SOFT_74xx:
1372    case POWERPC_MMU_SOFT_4xx:
1373    case POWERPC_MMU_REAL:
1374    case POWERPC_MMU_BOOKE:
1375        ctx->prot |= PAGE_WRITE;
1376        break;
1377
1378    case POWERPC_MMU_SOFT_4xx_Z:
1379        if (unlikely(msr_pe != 0)) {
1380            /*
1381             * 403 family add some particular protections, using
1382             * PBL/PBU registers for accesses with no translation.
1383             */
1384            in_plb =
1385                /* Check PLB validity */
1386                (env->pb[0] < env->pb[1] &&
1387                 /* and address in plb area */
1388                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1389                (env->pb[2] < env->pb[3] &&
1390                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1391            if (in_plb ^ msr_px) {
1392                /* Access in protected area */
1393                if (rw == 1) {
1394                    /* Access is not allowed */
1395                    ret = -2;
1396                }
1397            } else {
1398                /* Read-write access is allowed */
1399                ctx->prot |= PAGE_WRITE;
1400            }
1401        }
1402        break;
1403
1404    default:
1405        /* Caller's checks mean we should never get here for other models */
1406        abort();
1407        return -1;
1408    }
1409
1410    return ret;
1411}
1412
1413static int get_physical_address_wtlb(
1414    CPUPPCState *env, mmu_ctx_t *ctx,
1415    target_ulong eaddr, int rw, int access_type,
1416    int mmu_idx)
1417{
1418    int ret = -1;
1419    bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
1420        || (access_type != ACCESS_CODE && msr_dr == 0);
1421
1422    switch (env->mmu_model) {
1423    case POWERPC_MMU_SOFT_6xx:
1424    case POWERPC_MMU_SOFT_74xx:
1425        if (real_mode) {
1426            ret = check_physical(env, ctx, eaddr, rw);
1427        } else {
1428            /* Try to find a BAT */
1429            if (env->nb_BATs != 0) {
1430                ret = get_bat_6xx_tlb(env, ctx, eaddr, rw, access_type);
1431            }
1432            if (ret < 0) {
1433                /* We didn't match any BAT entry or don't have BATs */
1434                ret = get_segment_6xx_tlb(env, ctx, eaddr, rw, access_type);
1435            }
1436        }
1437        break;
1438
1439    case POWERPC_MMU_SOFT_4xx:
1440    case POWERPC_MMU_SOFT_4xx_Z:
1441        if (real_mode) {
1442            ret = check_physical(env, ctx, eaddr, rw);
1443        } else {
1444            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1445                                              rw, access_type);
1446        }
1447        break;
1448    case POWERPC_MMU_BOOKE:
1449        ret = mmubooke_get_physical_address(env, ctx, eaddr,
1450                                            rw, access_type);
1451        break;
1452    case POWERPC_MMU_BOOKE206:
1453        ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1454                                               access_type, mmu_idx);
1455        break;
1456    case POWERPC_MMU_MPC8xx:
1457        /* XXX: TODO */
1458        cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
1459        break;
1460    case POWERPC_MMU_REAL:
1461        if (real_mode) {
1462            ret = check_physical(env, ctx, eaddr, rw);
1463        } else {
1464            cpu_abort(env_cpu(env),
1465                      "PowerPC in real mode do not do any translation\n");
1466        }
1467        return -1;
1468    default:
1469        cpu_abort(env_cpu(env), "Unknown or invalid MMU model\n");
1470        return -1;
1471    }
1472
1473    return ret;
1474}
1475
1476static int get_physical_address(
1477    CPUPPCState *env, mmu_ctx_t *ctx,
1478    target_ulong eaddr, int rw, int access_type)
1479{
1480    return get_physical_address_wtlb(env, ctx, eaddr, rw, access_type, 0);
1481}
1482
1483hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
1484{
1485    PowerPCCPU *cpu = POWERPC_CPU(cs);
1486    CPUPPCState *env = &cpu->env;
1487    mmu_ctx_t ctx;
1488
1489    switch (env->mmu_model) {
1490#if defined(TARGET_PPC64)
1491    case POWERPC_MMU_64B:
1492    case POWERPC_MMU_2_03:
1493    case POWERPC_MMU_2_06:
1494    case POWERPC_MMU_2_07:
1495        return ppc_hash64_get_phys_page_debug(cpu, addr);
1496    case POWERPC_MMU_3_00:
1497        return ppc64_v3_get_phys_page_debug(cpu, addr);
1498#endif
1499
1500    case POWERPC_MMU_32B:
1501    case POWERPC_MMU_601:
1502        return ppc_hash32_get_phys_page_debug(cpu, addr);
1503
1504    default:
1505        ;
1506    }
1507
1508    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0)) {
1509
1510        /*
1511         * Some MMUs have separate TLBs for code and data. If we only
1512         * try an ACCESS_INT, we may not be able to read instructions
1513         * mapped by code TLBs, so we also try a ACCESS_CODE.
1514         */
1515        if (unlikely(get_physical_address(env, &ctx, addr, 0,
1516                                          ACCESS_CODE) != 0)) {
1517            return -1;
1518        }
1519    }
1520
1521    return ctx.raddr & TARGET_PAGE_MASK;
1522}
1523
1524static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
1525                                     int rw, int mmu_idx)
1526{
1527    uint32_t epid;
1528    bool as, pr;
1529    uint32_t missed_tid = 0;
1530    bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
1531    if (rw == 2) {
1532        as = msr_ir;
1533    }
1534    env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1535    env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1536    env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1537    env->spr[SPR_BOOKE_MAS3] = 0;
1538    env->spr[SPR_BOOKE_MAS6] = 0;
1539    env->spr[SPR_BOOKE_MAS7] = 0;
1540
1541    /* AS */
1542    if (as) {
1543        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1544        env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1545    }
1546
1547    env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1548    env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1549
1550    if (!use_epid) {
1551        switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1552        case MAS4_TIDSELD_PID0:
1553            missed_tid = env->spr[SPR_BOOKE_PID];
1554            break;
1555        case MAS4_TIDSELD_PID1:
1556            missed_tid = env->spr[SPR_BOOKE_PID1];
1557            break;
1558        case MAS4_TIDSELD_PID2:
1559            missed_tid = env->spr[SPR_BOOKE_PID2];
1560            break;
1561        }
1562        env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1563    } else {
1564        missed_tid = epid;
1565        env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
1566    }
1567    env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
1568
1569
1570    /* next victim logic */
1571    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1572    env->last_way++;
1573    env->last_way &= booke206_tlb_ways(env, 0) - 1;
1574    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1575}
1576
1577/* Perform address translation */
1578static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
1579                                    int rw, int mmu_idx)
1580{
1581    CPUState *cs = env_cpu(env);
1582    PowerPCCPU *cpu = POWERPC_CPU(cs);
1583    mmu_ctx_t ctx;
1584    int access_type;
1585    int ret = 0;
1586
1587    if (rw == 2) {
1588        /* code access */
1589        rw = 0;
1590        access_type = ACCESS_CODE;
1591    } else {
1592        /* data access */
1593        access_type = env->access_type;
1594    }
1595    ret = get_physical_address_wtlb(env, &ctx, address, rw,
1596                                    access_type, mmu_idx);
1597    if (ret == 0) {
1598        tlb_set_page(cs, address & TARGET_PAGE_MASK,
1599                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1600                     mmu_idx, TARGET_PAGE_SIZE);
1601        ret = 0;
1602    } else if (ret < 0) {
1603        LOG_MMU_STATE(cs);
1604        if (access_type == ACCESS_CODE) {
1605            switch (ret) {
1606            case -1:
1607                /* No matches in page tables or TLB */
1608                switch (env->mmu_model) {
1609                case POWERPC_MMU_SOFT_6xx:
1610                    cs->exception_index = POWERPC_EXCP_IFTLB;
1611                    env->error_code = 1 << 18;
1612                    env->spr[SPR_IMISS] = address;
1613                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1614                    goto tlb_miss;
1615                case POWERPC_MMU_SOFT_74xx:
1616                    cs->exception_index = POWERPC_EXCP_IFTLB;
1617                    goto tlb_miss_74xx;
1618                case POWERPC_MMU_SOFT_4xx:
1619                case POWERPC_MMU_SOFT_4xx_Z:
1620                    cs->exception_index = POWERPC_EXCP_ITLB;
1621                    env->error_code = 0;
1622                    env->spr[SPR_40x_DEAR] = address;
1623                    env->spr[SPR_40x_ESR] = 0x00000000;
1624                    break;
1625                case POWERPC_MMU_BOOKE206:
1626                    booke206_update_mas_tlb_miss(env, address, 2, mmu_idx);
1627                    /* fall through */
1628                case POWERPC_MMU_BOOKE:
1629                    cs->exception_index = POWERPC_EXCP_ITLB;
1630                    env->error_code = 0;
1631                    env->spr[SPR_BOOKE_DEAR] = address;
1632                    env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 0);
1633                    return -1;
1634                case POWERPC_MMU_MPC8xx:
1635                    /* XXX: TODO */
1636                    cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
1637                    break;
1638                case POWERPC_MMU_REAL:
1639                    cpu_abort(cs, "PowerPC in real mode should never raise "
1640                              "any MMU exceptions\n");
1641                    return -1;
1642                default:
1643                    cpu_abort(cs, "Unknown or invalid MMU model\n");
1644                    return -1;
1645                }
1646                break;
1647            case -2:
1648                /* Access rights violation */
1649                cs->exception_index = POWERPC_EXCP_ISI;
1650                env->error_code = 0x08000000;
1651                break;
1652            case -3:
1653                /* No execute protection violation */
1654                if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1655                    (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1656                    env->spr[SPR_BOOKE_ESR] = 0x00000000;
1657                }
1658                cs->exception_index = POWERPC_EXCP_ISI;
1659                env->error_code = 0x10000000;
1660                break;
1661            case -4:
1662                /* Direct store exception */
1663                /* No code fetch is allowed in direct-store areas */
1664                cs->exception_index = POWERPC_EXCP_ISI;
1665                env->error_code = 0x10000000;
1666                break;
1667            }
1668        } else {
1669            switch (ret) {
1670            case -1:
1671                /* No matches in page tables or TLB */
1672                switch (env->mmu_model) {
1673                case POWERPC_MMU_SOFT_6xx:
1674                    if (rw == 1) {
1675                        cs->exception_index = POWERPC_EXCP_DSTLB;
1676                        env->error_code = 1 << 16;
1677                    } else {
1678                        cs->exception_index = POWERPC_EXCP_DLTLB;
1679                        env->error_code = 0;
1680                    }
1681                    env->spr[SPR_DMISS] = address;
1682                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1683                tlb_miss:
1684                    env->error_code |= ctx.key << 19;
1685                    env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
1686                        get_pteg_offset32(cpu, ctx.hash[0]);
1687                    env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
1688                        get_pteg_offset32(cpu, ctx.hash[1]);
1689                    break;
1690                case POWERPC_MMU_SOFT_74xx:
1691                    if (rw == 1) {
1692                        cs->exception_index = POWERPC_EXCP_DSTLB;
1693                    } else {
1694                        cs->exception_index = POWERPC_EXCP_DLTLB;
1695                    }
1696                tlb_miss_74xx:
1697                    /* Implement LRU algorithm */
1698                    env->error_code = ctx.key << 19;
1699                    env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1700                        ((env->last_way + 1) & (env->nb_ways - 1));
1701                    env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1702                    break;
1703                case POWERPC_MMU_SOFT_4xx:
1704                case POWERPC_MMU_SOFT_4xx_Z:
1705                    cs->exception_index = POWERPC_EXCP_DTLB;
1706                    env->error_code = 0;
1707                    env->spr[SPR_40x_DEAR] = address;
1708                    if (rw) {
1709                        env->spr[SPR_40x_ESR] = 0x00800000;
1710                    } else {
1711                        env->spr[SPR_40x_ESR] = 0x00000000;
1712                    }
1713                    break;
1714                case POWERPC_MMU_MPC8xx:
1715                    /* XXX: TODO */
1716                    cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
1717                    break;
1718                case POWERPC_MMU_BOOKE206:
1719                    booke206_update_mas_tlb_miss(env, address, rw, mmu_idx);
1720                    /* fall through */
1721                case POWERPC_MMU_BOOKE:
1722                    cs->exception_index = POWERPC_EXCP_DTLB;
1723                    env->error_code = 0;
1724                    env->spr[SPR_BOOKE_DEAR] = address;
1725                    env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, rw);
1726                    return -1;
1727                case POWERPC_MMU_REAL:
1728                    cpu_abort(cs, "PowerPC in real mode should never raise "
1729                              "any MMU exceptions\n");
1730                    return -1;
1731                default:
1732                    cpu_abort(cs, "Unknown or invalid MMU model\n");
1733                    return -1;
1734                }
1735                break;
1736            case -2:
1737                /* Access rights violation */
1738                cs->exception_index = POWERPC_EXCP_DSI;
1739                env->error_code = 0;
1740                if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1741                    || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1742                    env->spr[SPR_40x_DEAR] = address;
1743                    if (rw) {
1744                        env->spr[SPR_40x_ESR] |= 0x00800000;
1745                    }
1746                } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1747                           (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1748                    env->spr[SPR_BOOKE_DEAR] = address;
1749                    env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, rw);
1750                } else {
1751                    env->spr[SPR_DAR] = address;
1752                    if (rw == 1) {
1753                        env->spr[SPR_DSISR] = 0x0A000000;
1754                    } else {
1755                        env->spr[SPR_DSISR] = 0x08000000;
1756                    }
1757                }
1758                break;
1759            case -4:
1760                /* Direct store exception */
1761                switch (access_type) {
1762                case ACCESS_FLOAT:
1763                    /* Floating point load/store */
1764                    cs->exception_index = POWERPC_EXCP_ALIGN;
1765                    env->error_code = POWERPC_EXCP_ALIGN_FP;
1766                    env->spr[SPR_DAR] = address;
1767                    break;
1768                case ACCESS_RES:
1769                    /* lwarx, ldarx or stwcx. */
1770                    cs->exception_index = POWERPC_EXCP_DSI;
1771                    env->error_code = 0;
1772                    env->spr[SPR_DAR] = address;
1773                    if (rw == 1) {
1774                        env->spr[SPR_DSISR] = 0x06000000;
1775                    } else {
1776                        env->spr[SPR_DSISR] = 0x04000000;
1777                    }
1778                    break;
1779                case ACCESS_EXT:
1780                    /* eciwx or ecowx */
1781                    cs->exception_index = POWERPC_EXCP_DSI;
1782                    env->error_code = 0;
1783                    env->spr[SPR_DAR] = address;
1784                    if (rw == 1) {
1785                        env->spr[SPR_DSISR] = 0x06100000;
1786                    } else {
1787                        env->spr[SPR_DSISR] = 0x04100000;
1788                    }
1789                    break;
1790                default:
1791                    printf("DSI: invalid exception (%d)\n", ret);
1792                    cs->exception_index = POWERPC_EXCP_PROGRAM;
1793                    env->error_code =
1794                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1795                    env->spr[SPR_DAR] = address;
1796                    break;
1797                }
1798                break;
1799            }
1800        }
1801        ret = 1;
1802    }
1803
1804    return ret;
1805}
1806
1807/*****************************************************************************/
1808/* BATs management */
1809#if !defined(FLUSH_ALL_TLBS)
1810static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1811                                     target_ulong mask)
1812{
1813    CPUState *cs = env_cpu(env);
1814    target_ulong base, end, page;
1815
1816    base = BATu & ~0x0001FFFF;
1817    end = base + mask + 0x00020000;
1818    if (((end - base) >> TARGET_PAGE_BITS) > 1024) {
1819        /* Flushing 1024 4K pages is slower than a complete flush */
1820        LOG_BATS("Flush all BATs\n");
1821        tlb_flush(CPU(cs));
1822        LOG_BATS("Flush done\n");
1823        return;
1824    }
1825    LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1826             TARGET_FMT_lx ")\n", base, end, mask);
1827    for (page = base; page != end; page += TARGET_PAGE_SIZE) {
1828        tlb_flush_page(cs, page);
1829    }
1830    LOG_BATS("Flush done\n");
1831}
1832#endif
1833
1834static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1835                                  target_ulong value)
1836{
1837    LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1838             nr, ul == 0 ? 'u' : 'l', value, env->nip);
1839}
1840
1841void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1842{
1843    target_ulong mask;
1844#if defined(FLUSH_ALL_TLBS)
1845    PowerPCCPU *cpu = env_archcpu(env);
1846#endif
1847
1848    dump_store_bat(env, 'I', 0, nr, value);
1849    if (env->IBAT[0][nr] != value) {
1850        mask = (value << 15) & 0x0FFE0000UL;
1851#if !defined(FLUSH_ALL_TLBS)
1852        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1853#endif
1854        /*
1855         * When storing valid upper BAT, mask BEPI and BRPN and
1856         * invalidate all TLBs covered by this BAT
1857         */
1858        mask = (value << 15) & 0x0FFE0000UL;
1859        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1860            (value & ~0x0001FFFFUL & ~mask);
1861        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1862            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1863#if !defined(FLUSH_ALL_TLBS)
1864        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1865#else
1866        tlb_flush(env_cpu(env));
1867#endif
1868    }
1869}
1870
1871void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1872{
1873    dump_store_bat(env, 'I', 1, nr, value);
1874    env->IBAT[1][nr] = value;
1875}
1876
1877void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1878{
1879    target_ulong mask;
1880#if defined(FLUSH_ALL_TLBS)
1881    PowerPCCPU *cpu = env_archcpu(env);
1882#endif
1883
1884    dump_store_bat(env, 'D', 0, nr, value);
1885    if (env->DBAT[0][nr] != value) {
1886        /*
1887         * When storing valid upper BAT, mask BEPI and BRPN and
1888         * invalidate all TLBs covered by this BAT
1889         */
1890        mask = (value << 15) & 0x0FFE0000UL;
1891#if !defined(FLUSH_ALL_TLBS)
1892        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1893#endif
1894        mask = (value << 15) & 0x0FFE0000UL;
1895        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1896            (value & ~0x0001FFFFUL & ~mask);
1897        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1898            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1899#if !defined(FLUSH_ALL_TLBS)
1900        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1901#else
1902        tlb_flush(env_cpu(env));
1903#endif
1904    }
1905}
1906
1907void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1908{
1909    dump_store_bat(env, 'D', 1, nr, value);
1910    env->DBAT[1][nr] = value;
1911}
1912
1913void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
1914{
1915    target_ulong mask;
1916#if defined(FLUSH_ALL_TLBS)
1917    PowerPCCPU *cpu = env_archcpu(env);
1918    int do_inval;
1919#endif
1920
1921    dump_store_bat(env, 'I', 0, nr, value);
1922    if (env->IBAT[0][nr] != value) {
1923#if defined(FLUSH_ALL_TLBS)
1924        do_inval = 0;
1925#endif
1926        mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1927        if (env->IBAT[1][nr] & 0x40) {
1928            /* Invalidate BAT only if it is valid */
1929#if !defined(FLUSH_ALL_TLBS)
1930            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1931#else
1932            do_inval = 1;
1933#endif
1934        }
1935        /*
1936         * When storing valid upper BAT, mask BEPI and BRPN and
1937         * invalidate all TLBs covered by this BAT
1938         */
1939        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1940            (value & ~0x0001FFFFUL & ~mask);
1941        env->DBAT[0][nr] = env->IBAT[0][nr];
1942        if (env->IBAT[1][nr] & 0x40) {
1943#if !defined(FLUSH_ALL_TLBS)
1944            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1945#else
1946            do_inval = 1;
1947#endif
1948        }
1949#if defined(FLUSH_ALL_TLBS)
1950        if (do_inval) {
1951            tlb_flush(env_cpu(env));
1952        }
1953#endif
1954    }
1955}
1956
1957void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
1958{
1959#if !defined(FLUSH_ALL_TLBS)
1960    target_ulong mask;
1961#else
1962    PowerPCCPU *cpu = env_archcpu(env);
1963    int do_inval;
1964#endif
1965
1966    dump_store_bat(env, 'I', 1, nr, value);
1967    if (env->IBAT[1][nr] != value) {
1968#if defined(FLUSH_ALL_TLBS)
1969        do_inval = 0;
1970#endif
1971        if (env->IBAT[1][nr] & 0x40) {
1972#if !defined(FLUSH_ALL_TLBS)
1973            mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1974            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1975#else
1976            do_inval = 1;
1977#endif
1978        }
1979        if (value & 0x40) {
1980#if !defined(FLUSH_ALL_TLBS)
1981            mask = (value << 17) & 0x0FFE0000UL;
1982            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1983#else
1984            do_inval = 1;
1985#endif
1986        }
1987        env->IBAT[1][nr] = value;
1988        env->DBAT[1][nr] = value;
1989#if defined(FLUSH_ALL_TLBS)
1990        if (do_inval) {
1991            tlb_flush(env_cpu(env));
1992        }
1993#endif
1994    }
1995}
1996
1997/*****************************************************************************/
1998/* TLB management */
1999void ppc_tlb_invalidate_all(CPUPPCState *env)
2000{
2001#if defined(TARGET_PPC64)
2002    if (env->mmu_model & POWERPC_MMU_64) {
2003        env->tlb_need_flush = 0;
2004        tlb_flush(env_cpu(env));
2005    } else
2006#endif /* defined(TARGET_PPC64) */
2007    switch (env->mmu_model) {
2008    case POWERPC_MMU_SOFT_6xx:
2009    case POWERPC_MMU_SOFT_74xx:
2010        ppc6xx_tlb_invalidate_all(env);
2011        break;
2012    case POWERPC_MMU_SOFT_4xx:
2013    case POWERPC_MMU_SOFT_4xx_Z:
2014        ppc4xx_tlb_invalidate_all(env);
2015        break;
2016    case POWERPC_MMU_REAL:
2017        cpu_abort(env_cpu(env), "No TLB for PowerPC 4xx in real mode\n");
2018        break;
2019    case POWERPC_MMU_MPC8xx:
2020        /* XXX: TODO */
2021        cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
2022        break;
2023    case POWERPC_MMU_BOOKE:
2024        tlb_flush(env_cpu(env));
2025        break;
2026    case POWERPC_MMU_BOOKE206:
2027        booke206_flush_tlb(env, -1, 0);
2028        break;
2029    case POWERPC_MMU_32B:
2030    case POWERPC_MMU_601:
2031        env->tlb_need_flush = 0;
2032        tlb_flush(env_cpu(env));
2033        break;
2034    default:
2035        /* XXX: TODO */
2036        cpu_abort(env_cpu(env), "Unknown MMU model %x\n", env->mmu_model);
2037        break;
2038    }
2039}
2040
2041void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
2042{
2043#if !defined(FLUSH_ALL_TLBS)
2044    addr &= TARGET_PAGE_MASK;
2045#if defined(TARGET_PPC64)
2046    if (env->mmu_model & POWERPC_MMU_64) {
2047        /* tlbie invalidate TLBs for all segments */
2048        /*
2049         * XXX: given the fact that there are too many segments to invalidate,
2050         *      and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
2051         *      we just invalidate all TLBs
2052         */
2053        env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2054    } else
2055#endif /* defined(TARGET_PPC64) */
2056    switch (env->mmu_model) {
2057    case POWERPC_MMU_SOFT_6xx:
2058    case POWERPC_MMU_SOFT_74xx:
2059        ppc6xx_tlb_invalidate_virt(env, addr, 0);
2060        if (env->id_tlbs == 1) {
2061            ppc6xx_tlb_invalidate_virt(env, addr, 1);
2062        }
2063        break;
2064    case POWERPC_MMU_32B:
2065    case POWERPC_MMU_601:
2066        /*
2067         * Actual CPUs invalidate entire congruence classes based on
2068         * the geometry of their TLBs and some OSes take that into
2069         * account, we just mark the TLB to be flushed later (context
2070         * synchronizing event or sync instruction on 32-bit).
2071         */
2072        env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2073        break;
2074    default:
2075        /* Should never reach here with other MMU models */
2076        assert(0);
2077    }
2078#else
2079    ppc_tlb_invalidate_all(env);
2080#endif
2081}
2082
2083/*****************************************************************************/
2084/* Special registers manipulation */
2085void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
2086{
2087    PowerPCCPU *cpu = env_archcpu(env);
2088    qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
2089    assert(!cpu->vhyp);
2090#if defined(TARGET_PPC64)
2091    if (env->mmu_model & POWERPC_MMU_64) {
2092        target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
2093        target_ulong htabsize = value & SDR_64_HTABSIZE;
2094
2095        if (value & ~sdr_mask) {
2096            error_report("Invalid bits 0x"TARGET_FMT_lx" set in SDR1",
2097                         value & ~sdr_mask);
2098            value &= sdr_mask;
2099        }
2100        if (htabsize > 28) {
2101            error_report("Invalid HTABSIZE 0x" TARGET_FMT_lx" stored in SDR1",
2102                         htabsize);
2103            return;
2104        }
2105    }
2106#endif /* defined(TARGET_PPC64) */
2107    /* FIXME: Should check for valid HTABMASK values in 32-bit case */
2108    env->spr[SPR_SDR1] = value;
2109}
2110
2111#if defined(TARGET_PPC64)
2112void ppc_store_ptcr(CPUPPCState *env, target_ulong value)
2113{
2114    PowerPCCPU *cpu = env_archcpu(env);
2115    target_ulong ptcr_mask = PTCR_PATB | PTCR_PATS;
2116    target_ulong patbsize = value & PTCR_PATS;
2117
2118    qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
2119
2120    assert(!cpu->vhyp);
2121    assert(env->mmu_model & POWERPC_MMU_3_00);
2122
2123    if (value & ~ptcr_mask) {
2124        error_report("Invalid bits 0x"TARGET_FMT_lx" set in PTCR",
2125                     value & ~ptcr_mask);
2126        value &= ptcr_mask;
2127    }
2128
2129    if (patbsize > 24) {
2130        error_report("Invalid Partition Table size 0x" TARGET_FMT_lx
2131                     " stored in PTCR", patbsize);
2132        return;
2133    }
2134
2135    env->spr[SPR_PTCR] = value;
2136}
2137
2138#endif /* defined(TARGET_PPC64) */
2139
2140/* Segment registers load and store */
2141target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
2142{
2143#if defined(TARGET_PPC64)
2144    if (env->mmu_model & POWERPC_MMU_64) {
2145        /* XXX */
2146        return 0;
2147    }
2148#endif
2149    return env->sr[sr_num];
2150}
2151
2152void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
2153{
2154    qemu_log_mask(CPU_LOG_MMU,
2155            "%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2156            (int)srnum, value, env->sr[srnum]);
2157#if defined(TARGET_PPC64)
2158    if (env->mmu_model & POWERPC_MMU_64) {
2159        PowerPCCPU *cpu = env_archcpu(env);
2160        uint64_t esid, vsid;
2161
2162        /* ESID = srnum */
2163        esid = ((uint64_t)(srnum & 0xf) << 28) | SLB_ESID_V;
2164
2165        /* VSID = VSID */
2166        vsid = (value & 0xfffffff) << 12;
2167        /* flags = flags */
2168        vsid |= ((value >> 27) & 0xf) << 8;
2169
2170        ppc_store_slb(cpu, srnum, esid, vsid);
2171    } else
2172#endif
2173    if (env->sr[srnum] != value) {
2174        env->sr[srnum] = value;
2175        /*
2176         * Invalidating 256MB of virtual memory in 4kB pages is way
2177         * longer than flusing the whole TLB.
2178         */
2179#if !defined(FLUSH_ALL_TLBS) && 0
2180        {
2181            target_ulong page, end;
2182            /* Invalidate 256 MB of virtual memory */
2183            page = (16 << 20) * srnum;
2184            end = page + (16 << 20);
2185            for (; page != end; page += TARGET_PAGE_SIZE) {
2186                tlb_flush_page(env_cpu(env), page);
2187            }
2188        }
2189#else
2190        env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2191#endif
2192    }
2193}
2194
2195/* TLB management */
2196void helper_tlbia(CPUPPCState *env)
2197{
2198    ppc_tlb_invalidate_all(env);
2199}
2200
2201void helper_tlbie(CPUPPCState *env, target_ulong addr)
2202{
2203    ppc_tlb_invalidate_one(env, addr);
2204}
2205
2206void helper_tlbiva(CPUPPCState *env, target_ulong addr)
2207{
2208    /* tlbiva instruction only exists on BookE */
2209    assert(env->mmu_model == POWERPC_MMU_BOOKE);
2210    /* XXX: TODO */
2211    cpu_abort(env_cpu(env), "BookE MMU model is not implemented\n");
2212}
2213
2214/* Software driven TLBs management */
2215/* PowerPC 602/603 software TLB load instructions helpers */
2216static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2217{
2218    target_ulong RPN, CMP, EPN;
2219    int way;
2220
2221    RPN = env->spr[SPR_RPA];
2222    if (is_code) {
2223        CMP = env->spr[SPR_ICMP];
2224        EPN = env->spr[SPR_IMISS];
2225    } else {
2226        CMP = env->spr[SPR_DCMP];
2227        EPN = env->spr[SPR_DMISS];
2228    }
2229    way = (env->spr[SPR_SRR1] >> 17) & 1;
2230    (void)EPN; /* avoid a compiler warning */
2231    LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2232              " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2233              RPN, way);
2234    /* Store this TLB */
2235    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2236                     way, is_code, CMP, RPN);
2237}
2238
2239void helper_6xx_tlbd(CPUPPCState *env, target_ulong EPN)
2240{
2241    do_6xx_tlb(env, EPN, 0);
2242}
2243
2244void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
2245{
2246    do_6xx_tlb(env, EPN, 1);
2247}
2248
2249/* PowerPC 74xx software TLB load instructions helpers */
2250static void do_74xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2251{
2252    target_ulong RPN, CMP, EPN;
2253    int way;
2254
2255    RPN = env->spr[SPR_PTELO];
2256    CMP = env->spr[SPR_PTEHI];
2257    EPN = env->spr[SPR_TLBMISS] & ~0x3;
2258    way = env->spr[SPR_TLBMISS] & 0x3;
2259    (void)EPN; /* avoid a compiler warning */
2260    LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2261              " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2262              RPN, way);
2263    /* Store this TLB */
2264    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2265                     way, is_code, CMP, RPN);
2266}
2267
2268void helper_74xx_tlbd(CPUPPCState *env, target_ulong EPN)
2269{
2270    do_74xx_tlb(env, EPN, 0);
2271}
2272
2273void helper_74xx_tlbi(CPUPPCState *env, target_ulong EPN)
2274{
2275    do_74xx_tlb(env, EPN, 1);
2276}
2277
2278/*****************************************************************************/
2279/* PowerPC 601 specific instructions (POWER bridge) */
2280
2281target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
2282{
2283    mmu_ctx_t ctx;
2284    int nb_BATs;
2285    target_ulong ret = 0;
2286
2287    /*
2288     * We don't have to generate many instances of this instruction,
2289     * as rac is supervisor only.
2290     *
2291     * XXX: FIX THIS: Pretend we have no BAT
2292     */
2293    nb_BATs = env->nb_BATs;
2294    env->nb_BATs = 0;
2295    if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) {
2296        ret = ctx.raddr;
2297    }
2298    env->nb_BATs = nb_BATs;
2299    return ret;
2300}
2301
2302static inline target_ulong booke_tlb_to_page_size(int size)
2303{
2304    return 1024 << (2 * size);
2305}
2306
2307static inline int booke_page_size_to_tlb(target_ulong page_size)
2308{
2309    int size;
2310
2311    switch (page_size) {
2312    case 0x00000400UL:
2313        size = 0x0;
2314        break;
2315    case 0x00001000UL:
2316        size = 0x1;
2317        break;
2318    case 0x00004000UL:
2319        size = 0x2;
2320        break;
2321    case 0x00010000UL:
2322        size = 0x3;
2323        break;
2324    case 0x00040000UL:
2325        size = 0x4;
2326        break;
2327    case 0x00100000UL:
2328        size = 0x5;
2329        break;
2330    case 0x00400000UL:
2331        size = 0x6;
2332        break;
2333    case 0x01000000UL:
2334        size = 0x7;
2335        break;
2336    case 0x04000000UL:
2337        size = 0x8;
2338        break;
2339    case 0x10000000UL:
2340        size = 0x9;
2341        break;
2342    case 0x40000000UL:
2343        size = 0xA;
2344        break;
2345#if defined(TARGET_PPC64)
2346    case 0x000100000000ULL:
2347        size = 0xB;
2348        break;
2349    case 0x000400000000ULL:
2350        size = 0xC;
2351        break;
2352    case 0x001000000000ULL:
2353        size = 0xD;
2354        break;
2355    case 0x004000000000ULL:
2356        size = 0xE;
2357        break;
2358    case 0x010000000000ULL:
2359        size = 0xF;
2360        break;
2361#endif
2362    default:
2363        size = -1;
2364        break;
2365    }
2366
2367    return size;
2368}
2369
2370/* Helpers for 4xx TLB management */
2371#define PPC4XX_TLB_ENTRY_MASK       0x0000003f  /* Mask for 64 TLB entries */
2372
2373#define PPC4XX_TLBHI_V              0x00000040
2374#define PPC4XX_TLBHI_E              0x00000020
2375#define PPC4XX_TLBHI_SIZE_MIN       0
2376#define PPC4XX_TLBHI_SIZE_MAX       7
2377#define PPC4XX_TLBHI_SIZE_DEFAULT   1
2378#define PPC4XX_TLBHI_SIZE_SHIFT     7
2379#define PPC4XX_TLBHI_SIZE_MASK      0x00000007
2380
2381#define PPC4XX_TLBLO_EX             0x00000200
2382#define PPC4XX_TLBLO_WR             0x00000100
2383#define PPC4XX_TLBLO_ATTR_MASK      0x000000FF
2384#define PPC4XX_TLBLO_RPN_MASK       0xFFFFFC00
2385
2386target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry)
2387{
2388    ppcemb_tlb_t *tlb;
2389    target_ulong ret;
2390    int size;
2391
2392    entry &= PPC4XX_TLB_ENTRY_MASK;
2393    tlb = &env->tlb.tlbe[entry];
2394    ret = tlb->EPN;
2395    if (tlb->prot & PAGE_VALID) {
2396        ret |= PPC4XX_TLBHI_V;
2397    }
2398    size = booke_page_size_to_tlb(tlb->size);
2399    if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) {
2400        size = PPC4XX_TLBHI_SIZE_DEFAULT;
2401    }
2402    ret |= size << PPC4XX_TLBHI_SIZE_SHIFT;
2403    env->spr[SPR_40x_PID] = tlb->PID;
2404    return ret;
2405}
2406
2407target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, target_ulong entry)
2408{
2409    ppcemb_tlb_t *tlb;
2410    target_ulong ret;
2411
2412    entry &= PPC4XX_TLB_ENTRY_MASK;
2413    tlb = &env->tlb.tlbe[entry];
2414    ret = tlb->RPN;
2415    if (tlb->prot & PAGE_EXEC) {
2416        ret |= PPC4XX_TLBLO_EX;
2417    }
2418    if (tlb->prot & PAGE_WRITE) {
2419        ret |= PPC4XX_TLBLO_WR;
2420    }
2421    return ret;
2422}
2423
2424void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
2425                         target_ulong val)
2426{
2427    CPUState *cs = env_cpu(env);
2428    ppcemb_tlb_t *tlb;
2429    target_ulong page, end;
2430
2431    LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
2432              val);
2433    entry &= PPC4XX_TLB_ENTRY_MASK;
2434    tlb = &env->tlb.tlbe[entry];
2435    /* Invalidate previous TLB (if it's valid) */
2436    if (tlb->prot & PAGE_VALID) {
2437        end = tlb->EPN + tlb->size;
2438        LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end "
2439                  TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2440        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2441            tlb_flush_page(cs, page);
2442        }
2443    }
2444    tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
2445                                       & PPC4XX_TLBHI_SIZE_MASK);
2446    /*
2447     * We cannot handle TLB size < TARGET_PAGE_SIZE.
2448     * If this ever occurs, we should implement TARGET_PAGE_BITS_VARY
2449     */
2450    if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
2451        cpu_abort(cs, "TLB size " TARGET_FMT_lu " < %u "
2452                  "are not supported (%d)\n"
2453                  "Please implement TARGET_PAGE_BITS_VARY\n",
2454                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
2455    }
2456    tlb->EPN = val & ~(tlb->size - 1);
2457    if (val & PPC4XX_TLBHI_V) {
2458        tlb->prot |= PAGE_VALID;
2459        if (val & PPC4XX_TLBHI_E) {
2460            /* XXX: TO BE FIXED */
2461            cpu_abort(cs,
2462                      "Little-endian TLB entries are not supported by now\n");
2463        }
2464    } else {
2465        tlb->prot &= ~PAGE_VALID;
2466    }
2467    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2468    LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2469              " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2470              (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2471              tlb->prot & PAGE_READ ? 'r' : '-',
2472              tlb->prot & PAGE_WRITE ? 'w' : '-',
2473              tlb->prot & PAGE_EXEC ? 'x' : '-',
2474              tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2475    /* Invalidate new TLB (if valid) */
2476    if (tlb->prot & PAGE_VALID) {
2477        end = tlb->EPN + tlb->size;
2478        LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end "
2479                  TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2480        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2481            tlb_flush_page(cs, page);
2482        }
2483    }
2484}
2485
2486void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry,
2487                         target_ulong val)
2488{
2489    ppcemb_tlb_t *tlb;
2490
2491    LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
2492              val);
2493    entry &= PPC4XX_TLB_ENTRY_MASK;
2494    tlb = &env->tlb.tlbe[entry];
2495    tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
2496    tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
2497    tlb->prot = PAGE_READ;
2498    if (val & PPC4XX_TLBLO_EX) {
2499        tlb->prot |= PAGE_EXEC;
2500    }
2501    if (val & PPC4XX_TLBLO_WR) {
2502        tlb->prot |= PAGE_WRITE;
2503    }
2504    LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2505              " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2506              (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2507              tlb->prot & PAGE_READ ? 'r' : '-',
2508              tlb->prot & PAGE_WRITE ? 'w' : '-',
2509              tlb->prot & PAGE_EXEC ? 'x' : '-',
2510              tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2511}
2512
2513target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address)
2514{
2515    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
2516}
2517
2518/* PowerPC 440 TLB management */
2519void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry,
2520                      target_ulong value)
2521{
2522    ppcemb_tlb_t *tlb;
2523    target_ulong EPN, RPN, size;
2524    int do_flush_tlbs;
2525
2526    LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n",
2527              __func__, word, (int)entry, value);
2528    do_flush_tlbs = 0;
2529    entry &= 0x3F;
2530    tlb = &env->tlb.tlbe[entry];
2531    switch (word) {
2532    default:
2533        /* Just here to please gcc */
2534    case 0:
2535        EPN = value & 0xFFFFFC00;
2536        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) {
2537            do_flush_tlbs = 1;
2538        }
2539        tlb->EPN = EPN;
2540        size = booke_tlb_to_page_size((value >> 4) & 0xF);
2541        if ((tlb->prot & PAGE_VALID) && tlb->size < size) {
2542            do_flush_tlbs = 1;
2543        }
2544        tlb->size = size;
2545        tlb->attr &= ~0x1;
2546        tlb->attr |= (value >> 8) & 1;
2547        if (value & 0x200) {
2548            tlb->prot |= PAGE_VALID;
2549        } else {
2550            if (tlb->prot & PAGE_VALID) {
2551                tlb->prot &= ~PAGE_VALID;
2552                do_flush_tlbs = 1;
2553            }
2554        }
2555        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2556        if (do_flush_tlbs) {
2557            tlb_flush(env_cpu(env));
2558        }
2559        break;
2560    case 1:
2561        RPN = value & 0xFFFFFC0F;
2562        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) {
2563            tlb_flush(env_cpu(env));
2564        }
2565        tlb->RPN = RPN;
2566        break;
2567    case 2:
2568        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
2569        tlb->prot = tlb->prot & PAGE_VALID;
2570        if (value & 0x1) {
2571            tlb->prot |= PAGE_READ << 4;
2572        }
2573        if (value & 0x2) {
2574            tlb->prot |= PAGE_WRITE << 4;
2575        }
2576        if (value & 0x4) {
2577            tlb->prot |= PAGE_EXEC << 4;
2578        }
2579        if (value & 0x8) {
2580            tlb->prot |= PAGE_READ;
2581        }
2582        if (value & 0x10) {
2583            tlb->prot |= PAGE_WRITE;
2584        }
2585        if (value & 0x20) {
2586            tlb->prot |= PAGE_EXEC;
2587        }
2588        break;
2589    }
2590}
2591
2592target_ulong helper_440_tlbre(CPUPPCState *env, uint32_t word,
2593                              target_ulong entry)
2594{
2595    ppcemb_tlb_t *tlb;
2596    target_ulong ret;
2597    int size;
2598
2599    entry &= 0x3F;
2600    tlb = &env->tlb.tlbe[entry];
2601    switch (word) {
2602    default:
2603        /* Just here to please gcc */
2604    case 0:
2605        ret = tlb->EPN;
2606        size = booke_page_size_to_tlb(tlb->size);
2607        if (size < 0 || size > 0xF) {
2608            size = 1;
2609        }
2610        ret |= size << 4;
2611        if (tlb->attr & 0x1) {
2612            ret |= 0x100;
2613        }
2614        if (tlb->prot & PAGE_VALID) {
2615            ret |= 0x200;
2616        }
2617        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2618        env->spr[SPR_440_MMUCR] |= tlb->PID;
2619        break;
2620    case 1:
2621        ret = tlb->RPN;
2622        break;
2623    case 2:
2624        ret = tlb->attr & ~0x1;
2625        if (tlb->prot & (PAGE_READ << 4)) {
2626            ret |= 0x1;
2627        }
2628        if (tlb->prot & (PAGE_WRITE << 4)) {
2629            ret |= 0x2;
2630        }
2631        if (tlb->prot & (PAGE_EXEC << 4)) {
2632            ret |= 0x4;
2633        }
2634        if (tlb->prot & PAGE_READ) {
2635            ret |= 0x8;
2636        }
2637        if (tlb->prot & PAGE_WRITE) {
2638            ret |= 0x10;
2639        }
2640        if (tlb->prot & PAGE_EXEC) {
2641            ret |= 0x20;
2642        }
2643        break;
2644    }
2645    return ret;
2646}
2647
2648target_ulong helper_440_tlbsx(CPUPPCState *env, target_ulong address)
2649{
2650    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
2651}
2652
2653/* PowerPC BookE 2.06 TLB management */
2654
2655static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env)
2656{
2657    uint32_t tlbncfg = 0;
2658    int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
2659    int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
2660    int tlb;
2661
2662    tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2663    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
2664
2665    if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
2666        cpu_abort(env_cpu(env), "we don't support HES yet\n");
2667    }
2668
2669    return booke206_get_tlbm(env, tlb, ea, esel);
2670}
2671
2672void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid)
2673{
2674    env->spr[pidn] = pid;
2675    /* changing PIDs mean we're in a different address space now */
2676    tlb_flush(env_cpu(env));
2677}
2678
2679void helper_booke_set_eplc(CPUPPCState *env, target_ulong val)
2680{
2681    env->spr[SPR_BOOKE_EPLC] = val & EPID_MASK;
2682    tlb_flush_by_mmuidx(env_cpu(env), 1 << PPC_TLB_EPID_LOAD);
2683}
2684void helper_booke_set_epsc(CPUPPCState *env, target_ulong val)
2685{
2686    env->spr[SPR_BOOKE_EPSC] = val & EPID_MASK;
2687    tlb_flush_by_mmuidx(env_cpu(env), 1 << PPC_TLB_EPID_STORE);
2688}
2689
2690static inline void flush_page(CPUPPCState *env, ppcmas_tlb_t *tlb)
2691{
2692    if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
2693        tlb_flush_page(env_cpu(env), tlb->mas2 & MAS2_EPN_MASK);
2694    } else {
2695        tlb_flush(env_cpu(env));
2696    }
2697}
2698
2699void helper_booke206_tlbwe(CPUPPCState *env)
2700{
2701    uint32_t tlbncfg, tlbn;
2702    ppcmas_tlb_t *tlb;
2703    uint32_t size_tlb, size_ps;
2704    target_ulong mask;
2705
2706
2707    switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
2708    case MAS0_WQ_ALWAYS:
2709        /* good to go, write that entry */
2710        break;
2711    case MAS0_WQ_COND:
2712        /* XXX check if reserved */
2713        if (0) {
2714            return;
2715        }
2716        break;
2717    case MAS0_WQ_CLR_RSRV:
2718        /* XXX clear entry */
2719        return;
2720    default:
2721        /* no idea what to do */
2722        return;
2723    }
2724
2725    if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
2726        !msr_gs) {
2727        /* XXX we don't support direct LRAT setting yet */
2728        fprintf(stderr, "cpu: don't support LRAT setting yet\n");
2729        return;
2730    }
2731
2732    tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2733    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
2734
2735    tlb = booke206_cur_tlb(env);
2736
2737    if (!tlb) {
2738        raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2739                               POWERPC_EXCP_INVAL |
2740                               POWERPC_EXCP_INVAL_INVAL, GETPC());
2741    }
2742
2743    /* check that we support the targeted size */
2744    size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
2745    size_ps = booke206_tlbnps(env, tlbn);
2746    if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
2747        !(size_ps & (1 << size_tlb))) {
2748        raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2749                               POWERPC_EXCP_INVAL |
2750                               POWERPC_EXCP_INVAL_INVAL, GETPC());
2751    }
2752
2753    if (msr_gs) {
2754        cpu_abort(env_cpu(env), "missing HV implementation\n");
2755    }
2756
2757    if (tlb->mas1 & MAS1_VALID) {
2758        /*
2759         * Invalidate the page in QEMU TLB if it was a valid entry.
2760         *
2761         * In "PowerPC e500 Core Family Reference Manual, Rev. 1",
2762         * Section "12.4.2 TLB Write Entry (tlbwe) Instruction":
2763         * (https://www.nxp.com/docs/en/reference-manual/E500CORERM.pdf)
2764         *
2765         * "Note that when an L2 TLB entry is written, it may be displacing an
2766         * already valid entry in the same L2 TLB location (a victim). If a
2767         * valid L1 TLB entry corresponds to the L2 MMU victim entry, that L1
2768         * TLB entry is automatically invalidated."
2769         */
2770        flush_page(env, tlb);
2771    }
2772
2773    tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
2774        env->spr[SPR_BOOKE_MAS3];
2775    tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
2776
2777    if ((env->spr[SPR_MMUCFG] & MMUCFG_MAVN) == MMUCFG_MAVN_V2) {
2778        /* For TLB which has a fixed size TSIZE is ignored with MAV2 */
2779        booke206_fixed_size_tlbn(env, tlbn, tlb);
2780    } else {
2781        if (!(tlbncfg & TLBnCFG_AVAIL)) {
2782            /* force !AVAIL TLB entries to correct page size */
2783            tlb->mas1 &= ~MAS1_TSIZE_MASK;
2784            /* XXX can be configured in MMUCSR0 */
2785            tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
2786        }
2787    }
2788
2789    /* Make a mask from TLB size to discard invalid bits in EPN field */
2790    mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2791    /* Add a mask for page attributes */
2792    mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E;
2793
2794    if (!msr_cm) {
2795        /*
2796         * Executing a tlbwe instruction in 32-bit mode will set bits
2797         * 0:31 of the TLB EPN field to zero.
2798         */
2799        mask &= 0xffffffff;
2800    }
2801
2802    tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask;
2803
2804    if (!(tlbncfg & TLBnCFG_IPROT)) {
2805        /* no IPROT supported by TLB */
2806        tlb->mas1 &= ~MAS1_IPROT;
2807    }
2808
2809    flush_page(env, tlb);
2810}
2811
2812static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb)
2813{
2814    int tlbn = booke206_tlbm_to_tlbn(env, tlb);
2815    int way = booke206_tlbm_to_way(env, tlb);
2816
2817    env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
2818    env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
2819    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2820
2821    env->spr[SPR_BOOKE_MAS1] = tlb->mas1;
2822    env->spr[SPR_BOOKE_MAS2] = tlb->mas2;
2823    env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3;
2824    env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32;
2825}
2826
2827void helper_booke206_tlbre(CPUPPCState *env)
2828{
2829    ppcmas_tlb_t *tlb = NULL;
2830
2831    tlb = booke206_cur_tlb(env);
2832    if (!tlb) {
2833        env->spr[SPR_BOOKE_MAS1] = 0;
2834    } else {
2835        booke206_tlb_to_mas(env, tlb);
2836    }
2837}
2838
2839void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address)
2840{
2841    ppcmas_tlb_t *tlb = NULL;
2842    int i, j;
2843    hwaddr raddr;
2844    uint32_t spid, sas;
2845
2846    spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
2847    sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
2848
2849    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2850        int ways = booke206_tlb_ways(env, i);
2851
2852        for (j = 0; j < ways; j++) {
2853            tlb = booke206_get_tlbm(env, i, address, j);
2854
2855            if (!tlb) {
2856                continue;
2857            }
2858
2859            if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
2860                continue;
2861            }
2862
2863            if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
2864                continue;
2865            }
2866
2867            booke206_tlb_to_mas(env, tlb);
2868            return;
2869        }
2870    }
2871
2872    /* no entry found, fill with defaults */
2873    env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
2874    env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
2875    env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
2876    env->spr[SPR_BOOKE_MAS3] = 0;
2877    env->spr[SPR_BOOKE_MAS7] = 0;
2878
2879    if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
2880        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
2881    }
2882
2883    env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
2884        << MAS1_TID_SHIFT;
2885
2886    /* next victim logic */
2887    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
2888    env->last_way++;
2889    env->last_way &= booke206_tlb_ways(env, 0) - 1;
2890    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2891}
2892
2893static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
2894                                              uint32_t ea)
2895{
2896    int i;
2897    int ways = booke206_tlb_ways(env, tlbn);
2898    target_ulong mask;
2899
2900    for (i = 0; i < ways; i++) {
2901        ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
2902        if (!tlb) {
2903            continue;
2904        }
2905        mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2906        if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
2907            !(tlb->mas1 & MAS1_IPROT)) {
2908            tlb->mas1 &= ~MAS1_VALID;
2909        }
2910    }
2911}
2912
2913void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
2914{
2915    CPUState *cs;
2916
2917    if (address & 0x4) {
2918        /* flush all entries */
2919        if (address & 0x8) {
2920            /* flush all of TLB1 */
2921            booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
2922        } else {
2923            /* flush all of TLB0 */
2924            booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
2925        }
2926        return;
2927    }
2928
2929    if (address & 0x8) {
2930        /* flush TLB1 entries */
2931        booke206_invalidate_ea_tlb(env, 1, address);
2932        CPU_FOREACH(cs) {
2933            tlb_flush(cs);
2934        }
2935    } else {
2936        /* flush TLB0 entries */
2937        booke206_invalidate_ea_tlb(env, 0, address);
2938        CPU_FOREACH(cs) {
2939            tlb_flush_page(cs, address & MAS2_EPN_MASK);
2940        }
2941    }
2942}
2943
2944void helper_booke206_tlbilx0(CPUPPCState *env, target_ulong address)
2945{
2946    /* XXX missing LPID handling */
2947    booke206_flush_tlb(env, -1, 1);
2948}
2949
2950void helper_booke206_tlbilx1(CPUPPCState *env, target_ulong address)
2951{
2952    int i, j;
2953    int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2954    ppcmas_tlb_t *tlb = env->tlb.tlbm;
2955    int tlb_size;
2956
2957    /* XXX missing LPID handling */
2958    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2959        tlb_size = booke206_tlb_size(env, i);
2960        for (j = 0; j < tlb_size; j++) {
2961            if (!(tlb[j].mas1 & MAS1_IPROT) &&
2962                ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
2963                tlb[j].mas1 &= ~MAS1_VALID;
2964            }
2965        }
2966        tlb += booke206_tlb_size(env, i);
2967    }
2968    tlb_flush(env_cpu(env));
2969}
2970
2971void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address)
2972{
2973    int i, j;
2974    ppcmas_tlb_t *tlb;
2975    int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2976    int pid = tid >> MAS6_SPID_SHIFT;
2977    int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
2978    int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
2979    /* XXX check for unsupported isize and raise an invalid opcode then */
2980    int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
2981    /* XXX implement MAV2 handling */
2982    bool mav2 = false;
2983
2984    /* XXX missing LPID handling */
2985    /* flush by pid and ea */
2986    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2987        int ways = booke206_tlb_ways(env, i);
2988
2989        for (j = 0; j < ways; j++) {
2990            tlb = booke206_get_tlbm(env, i, address, j);
2991            if (!tlb) {
2992                continue;
2993            }
2994            if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
2995                (tlb->mas1 & MAS1_IPROT) ||
2996                ((tlb->mas1 & MAS1_IND) != ind) ||
2997                ((tlb->mas8 & MAS8_TGS) != sgs)) {
2998                continue;
2999            }
3000            if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
3001                /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
3002                continue;
3003            }
3004            /* XXX e500mc doesn't match SAS, but other cores might */
3005            tlb->mas1 &= ~MAS1_VALID;
3006        }
3007    }
3008    tlb_flush(env_cpu(env));
3009}
3010
3011void helper_booke206_tlbflush(CPUPPCState *env, target_ulong type)
3012{
3013    int flags = 0;
3014
3015    if (type & 2) {
3016        flags |= BOOKE206_FLUSH_TLB1;
3017    }
3018
3019    if (type & 4) {
3020        flags |= BOOKE206_FLUSH_TLB0;
3021    }
3022
3023    booke206_flush_tlb(env, flags, 1);
3024}
3025
3026
3027void helper_check_tlb_flush_local(CPUPPCState *env)
3028{
3029    check_tlb_flush(env, false);
3030}
3031
3032void helper_check_tlb_flush_global(CPUPPCState *env)
3033{
3034    check_tlb_flush(env, true);
3035}
3036
3037/*****************************************************************************/
3038
3039bool ppc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
3040                      MMUAccessType access_type, int mmu_idx,
3041                      bool probe, uintptr_t retaddr)
3042{
3043    PowerPCCPU *cpu = POWERPC_CPU(cs);
3044    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
3045    CPUPPCState *env = &cpu->env;
3046    int ret;
3047
3048    if (pcc->handle_mmu_fault) {
3049        ret = pcc->handle_mmu_fault(cpu, addr, access_type, mmu_idx);
3050    } else {
3051        ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx);
3052    }
3053    if (unlikely(ret != 0)) {
3054        if (probe) {
3055            return false;
3056        }
3057        raise_exception_err_ra(env, cs->exception_index, env->error_code,
3058                               retaddr);
3059    }
3060    return true;
3061}
3062