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