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