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_radix_guest(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#if 0
1419    qemu_log("%s\n", __func__);
1420#endif
1421
1422    switch (env->mmu_model) {
1423    case POWERPC_MMU_SOFT_6xx:
1424    case POWERPC_MMU_SOFT_74xx:
1425        if (real_mode) {
1426            ret = check_physical(env, ctx, eaddr, rw);
1427        } else {
1428            /* Try to find a BAT */
1429            if (env->nb_BATs != 0) {
1430                ret = get_bat_6xx_tlb(env, ctx, eaddr, rw, access_type);
1431            }
1432            if (ret < 0) {
1433                /* We didn't match any BAT entry or don't have BATs */
1434                ret = get_segment_6xx_tlb(env, ctx, eaddr, rw, access_type);
1435            }
1436        }
1437        break;
1438
1439    case POWERPC_MMU_SOFT_4xx:
1440    case POWERPC_MMU_SOFT_4xx_Z:
1441        if (real_mode) {
1442            ret = check_physical(env, ctx, eaddr, rw);
1443        } else {
1444            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1445                                              rw, access_type);
1446        }
1447        break;
1448    case POWERPC_MMU_BOOKE:
1449        ret = mmubooke_get_physical_address(env, ctx, eaddr,
1450                                            rw, access_type);
1451        break;
1452    case POWERPC_MMU_BOOKE206:
1453        ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1454                                               access_type, mmu_idx);
1455        break;
1456    case POWERPC_MMU_MPC8xx:
1457        /* XXX: TODO */
1458        cpu_abort(CPU(cpu), "MPC8xx MMU model is not implemented\n");
1459        break;
1460    case POWERPC_MMU_REAL:
1461        if (real_mode) {
1462            ret = check_physical(env, ctx, eaddr, rw);
1463        } else {
1464            cpu_abort(CPU(cpu), "PowerPC in real mode do not do any translation\n");
1465        }
1466        return -1;
1467    default:
1468        cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n");
1469        return -1;
1470    }
1471#if 0
1472    qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1473             __func__, eaddr, ret, ctx->raddr);
1474#endif
1475
1476    return ret;
1477}
1478
1479static int get_physical_address(
1480    CPUPPCState *env, mmu_ctx_t *ctx,
1481    target_ulong eaddr, int rw, int access_type)
1482{
1483    return get_physical_address_wtlb(env, ctx, eaddr, rw, access_type, 0);
1484}
1485
1486hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
1487{
1488    PowerPCCPU *cpu = POWERPC_CPU(cs);
1489    CPUPPCState *env = &cpu->env;
1490    mmu_ctx_t ctx;
1491
1492    switch (env->mmu_model) {
1493#if defined(TARGET_PPC64)
1494    case POWERPC_MMU_64B:
1495    case POWERPC_MMU_2_03:
1496    case POWERPC_MMU_2_06:
1497    case POWERPC_MMU_2_07:
1498        return ppc_hash64_get_phys_page_debug(cpu, addr);
1499    case POWERPC_MMU_3_00:
1500        if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
1501            return ppc_radix64_get_phys_page_debug(cpu, addr);
1502        } else {
1503            return ppc_hash64_get_phys_page_debug(cpu, addr);
1504        }
1505        break;
1506#endif
1507
1508    case POWERPC_MMU_32B:
1509    case POWERPC_MMU_601:
1510        return ppc_hash32_get_phys_page_debug(cpu, addr);
1511
1512    default:
1513        ;
1514    }
1515
1516    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0)) {
1517
1518        /* Some MMUs have separate TLBs for code and data. If we only try an
1519         * ACCESS_INT, we may not be able to read instructions mapped by code
1520         * TLBs, so we also try a ACCESS_CODE.
1521         */
1522        if (unlikely(get_physical_address(env, &ctx, addr, 0,
1523                                          ACCESS_CODE) != 0)) {
1524            return -1;
1525        }
1526    }
1527
1528    return ctx.raddr & TARGET_PAGE_MASK;
1529}
1530
1531static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
1532                                     int rw, int mmu_idx)
1533{
1534    uint32_t epid;
1535    bool as, pr;
1536    uint32_t missed_tid = 0;
1537    bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
1538    if (rw == 2) {
1539        as = msr_ir;
1540    }
1541    env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1542    env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1543    env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1544    env->spr[SPR_BOOKE_MAS3] = 0;
1545    env->spr[SPR_BOOKE_MAS6] = 0;
1546    env->spr[SPR_BOOKE_MAS7] = 0;
1547
1548    /* AS */
1549    if (as) {
1550        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1551        env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1552    }
1553
1554    env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1555    env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1556
1557    if (!use_epid) {
1558        switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1559        case MAS4_TIDSELD_PID0:
1560            missed_tid = env->spr[SPR_BOOKE_PID];
1561            break;
1562        case MAS4_TIDSELD_PID1:
1563            missed_tid = env->spr[SPR_BOOKE_PID1];
1564            break;
1565        case MAS4_TIDSELD_PID2:
1566            missed_tid = env->spr[SPR_BOOKE_PID2];
1567            break;
1568        }
1569        env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1570    } else {
1571        missed_tid = epid;
1572        env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
1573    }
1574    env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
1575
1576
1577    /* next victim logic */
1578    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1579    env->last_way++;
1580    env->last_way &= booke206_tlb_ways(env, 0) - 1;
1581    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1582}
1583
1584/* Perform address translation */
1585static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
1586                                    int rw, int mmu_idx)
1587{
1588    CPUState *cs = CPU(ppc_env_get_cpu(env));
1589    PowerPCCPU *cpu = POWERPC_CPU(cs);
1590    mmu_ctx_t ctx;
1591    int access_type;
1592    int ret = 0;
1593
1594    if (rw == 2) {
1595        /* code access */
1596        rw = 0;
1597        access_type = ACCESS_CODE;
1598    } else {
1599        /* data access */
1600        access_type = env->access_type;
1601    }
1602    ret = get_physical_address_wtlb(env, &ctx, address, rw,
1603                                    access_type, mmu_idx);
1604    if (ret == 0) {
1605        tlb_set_page(cs, address & TARGET_PAGE_MASK,
1606                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1607                     mmu_idx, TARGET_PAGE_SIZE);
1608        ret = 0;
1609    } else if (ret < 0) {
1610        LOG_MMU_STATE(cs);
1611        if (access_type == ACCESS_CODE) {
1612            switch (ret) {
1613            case -1:
1614                /* No matches in page tables or TLB */
1615                switch (env->mmu_model) {
1616                case POWERPC_MMU_SOFT_6xx:
1617                    cs->exception_index = POWERPC_EXCP_IFTLB;
1618                    env->error_code = 1 << 18;
1619                    env->spr[SPR_IMISS] = address;
1620                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1621                    goto tlb_miss;
1622                case POWERPC_MMU_SOFT_74xx:
1623                    cs->exception_index = POWERPC_EXCP_IFTLB;
1624                    goto tlb_miss_74xx;
1625                case POWERPC_MMU_SOFT_4xx:
1626                case POWERPC_MMU_SOFT_4xx_Z:
1627                    cs->exception_index = POWERPC_EXCP_ITLB;
1628                    env->error_code = 0;
1629                    env->spr[SPR_40x_DEAR] = address;
1630                    env->spr[SPR_40x_ESR] = 0x00000000;
1631                    break;
1632                case POWERPC_MMU_BOOKE206:
1633                    booke206_update_mas_tlb_miss(env, address, 2, mmu_idx);
1634                    /* fall through */
1635                case POWERPC_MMU_BOOKE:
1636                    cs->exception_index = POWERPC_EXCP_ITLB;
1637                    env->error_code = 0;
1638                    env->spr[SPR_BOOKE_DEAR] = address;
1639                    env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 0);
1640                    return -1;
1641                case POWERPC_MMU_MPC8xx:
1642                    /* XXX: TODO */
1643                    cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
1644                    break;
1645                case POWERPC_MMU_REAL:
1646                    cpu_abort(cs, "PowerPC in real mode should never raise "
1647                              "any MMU exceptions\n");
1648                    return -1;
1649                default:
1650                    cpu_abort(cs, "Unknown or invalid MMU model\n");
1651                    return -1;
1652                }
1653                break;
1654            case -2:
1655                /* Access rights violation */
1656                cs->exception_index = POWERPC_EXCP_ISI;
1657                env->error_code = 0x08000000;
1658                break;
1659            case -3:
1660                /* No execute protection violation */
1661                if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1662                    (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1663                    env->spr[SPR_BOOKE_ESR] = 0x00000000;
1664                }
1665                cs->exception_index = POWERPC_EXCP_ISI;
1666                env->error_code = 0x10000000;
1667                break;
1668            case -4:
1669                /* Direct store exception */
1670                /* No code fetch is allowed in direct-store areas */
1671                cs->exception_index = POWERPC_EXCP_ISI;
1672                env->error_code = 0x10000000;
1673                break;
1674            }
1675        } else {
1676            switch (ret) {
1677            case -1:
1678                /* No matches in page tables or TLB */
1679                switch (env->mmu_model) {
1680                case POWERPC_MMU_SOFT_6xx:
1681                    if (rw == 1) {
1682                        cs->exception_index = POWERPC_EXCP_DSTLB;
1683                        env->error_code = 1 << 16;
1684                    } else {
1685                        cs->exception_index = POWERPC_EXCP_DLTLB;
1686                        env->error_code = 0;
1687                    }
1688                    env->spr[SPR_DMISS] = address;
1689                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1690                tlb_miss:
1691                    env->error_code |= ctx.key << 19;
1692                    env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
1693                        get_pteg_offset32(cpu, ctx.hash[0]);
1694                    env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
1695                        get_pteg_offset32(cpu, ctx.hash[1]);
1696                    break;
1697                case POWERPC_MMU_SOFT_74xx:
1698                    if (rw == 1) {
1699                        cs->exception_index = POWERPC_EXCP_DSTLB;
1700                    } else {
1701                        cs->exception_index = POWERPC_EXCP_DLTLB;
1702                    }
1703                tlb_miss_74xx:
1704                    /* Implement LRU algorithm */
1705                    env->error_code = ctx.key << 19;
1706                    env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1707                        ((env->last_way + 1) & (env->nb_ways - 1));
1708                    env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1709                    break;
1710                case POWERPC_MMU_SOFT_4xx:
1711                case POWERPC_MMU_SOFT_4xx_Z:
1712                    cs->exception_index = POWERPC_EXCP_DTLB;
1713                    env->error_code = 0;
1714                    env->spr[SPR_40x_DEAR] = address;
1715                    if (rw) {
1716                        env->spr[SPR_40x_ESR] = 0x00800000;
1717                    } else {
1718                        env->spr[SPR_40x_ESR] = 0x00000000;
1719                    }
1720                    break;
1721                case POWERPC_MMU_MPC8xx:
1722                    /* XXX: TODO */
1723                    cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
1724                    break;
1725                case POWERPC_MMU_BOOKE206:
1726                    booke206_update_mas_tlb_miss(env, address, rw, mmu_idx);
1727                    /* fall through */
1728                case POWERPC_MMU_BOOKE:
1729                    cs->exception_index = POWERPC_EXCP_DTLB;
1730                    env->error_code = 0;
1731                    env->spr[SPR_BOOKE_DEAR] = address;
1732                    env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, rw);
1733                    return -1;
1734                case POWERPC_MMU_REAL:
1735                    cpu_abort(cs, "PowerPC in real mode should never raise "
1736                              "any MMU exceptions\n");
1737                    return -1;
1738                default:
1739                    cpu_abort(cs, "Unknown or invalid MMU model\n");
1740                    return -1;
1741                }
1742                break;
1743            case -2:
1744                /* Access rights violation */
1745                cs->exception_index = POWERPC_EXCP_DSI;
1746                env->error_code = 0;
1747                if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1748                    || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1749                    env->spr[SPR_40x_DEAR] = address;
1750                    if (rw) {
1751                        env->spr[SPR_40x_ESR] |= 0x00800000;
1752                    }
1753                } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1754                           (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1755                    env->spr[SPR_BOOKE_DEAR] = address;
1756                    env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, rw);
1757                } else {
1758                    env->spr[SPR_DAR] = address;
1759                    if (rw == 1) {
1760                        env->spr[SPR_DSISR] = 0x0A000000;
1761                    } else {
1762                        env->spr[SPR_DSISR] = 0x08000000;
1763                    }
1764                }
1765                break;
1766            case -4:
1767                /* Direct store exception */
1768                switch (access_type) {
1769                case ACCESS_FLOAT:
1770                    /* Floating point load/store */
1771                    cs->exception_index = POWERPC_EXCP_ALIGN;
1772                    env->error_code = POWERPC_EXCP_ALIGN_FP;
1773                    env->spr[SPR_DAR] = address;
1774                    break;
1775                case ACCESS_RES:
1776                    /* lwarx, ldarx or stwcx. */
1777                    cs->exception_index = POWERPC_EXCP_DSI;
1778                    env->error_code = 0;
1779                    env->spr[SPR_DAR] = address;
1780                    if (rw == 1) {
1781                        env->spr[SPR_DSISR] = 0x06000000;
1782                    } else {
1783                        env->spr[SPR_DSISR] = 0x04000000;
1784                    }
1785                    break;
1786                case ACCESS_EXT:
1787                    /* eciwx or ecowx */
1788                    cs->exception_index = POWERPC_EXCP_DSI;
1789                    env->error_code = 0;
1790                    env->spr[SPR_DAR] = address;
1791                    if (rw == 1) {
1792                        env->spr[SPR_DSISR] = 0x06100000;
1793                    } else {
1794                        env->spr[SPR_DSISR] = 0x04100000;
1795                    }
1796                    break;
1797                default:
1798                    printf("DSI: invalid exception (%d)\n", ret);
1799                    cs->exception_index = POWERPC_EXCP_PROGRAM;
1800                    env->error_code =
1801                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1802                    env->spr[SPR_DAR] = address;
1803                    break;
1804                }
1805                break;
1806            }
1807        }
1808#if 0
1809        printf("%s: set exception to %d %02x\n", __func__,
1810               cs->exception, env->error_code);
1811#endif
1812        ret = 1;
1813    }
1814
1815    return ret;
1816}
1817
1818/*****************************************************************************/
1819/* BATs management */
1820#if !defined(FLUSH_ALL_TLBS)
1821static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1822                                     target_ulong mask)
1823{
1824    CPUState *cs = CPU(ppc_env_get_cpu(env));
1825    target_ulong base, end, page;
1826
1827    base = BATu & ~0x0001FFFF;
1828    end = base + mask + 0x00020000;
1829    LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1830             TARGET_FMT_lx ")\n", base, end, mask);
1831    for (page = base; page != end; page += TARGET_PAGE_SIZE) {
1832        tlb_flush_page(cs, page);
1833    }
1834    LOG_BATS("Flush done\n");
1835}
1836#endif
1837
1838static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1839                                  target_ulong value)
1840{
1841    LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1842             nr, ul == 0 ? 'u' : 'l', value, env->nip);
1843}
1844
1845void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1846{
1847    target_ulong mask;
1848#if defined(FLUSH_ALL_TLBS)
1849    PowerPCCPU *cpu = ppc_env_get_cpu(env);
1850#endif
1851
1852    dump_store_bat(env, 'I', 0, nr, value);
1853    if (env->IBAT[0][nr] != value) {
1854        mask = (value << 15) & 0x0FFE0000UL;
1855#if !defined(FLUSH_ALL_TLBS)
1856        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1857#endif
1858        /* When storing valid upper BAT, mask BEPI and BRPN
1859         * and invalidate all TLBs covered by this BAT
1860         */
1861        mask = (value << 15) & 0x0FFE0000UL;
1862        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1863            (value & ~0x0001FFFFUL & ~mask);
1864        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1865            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1866#if !defined(FLUSH_ALL_TLBS)
1867        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1868#else
1869        tlb_flush(CPU(cpu));
1870#endif
1871    }
1872}
1873
1874void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1875{
1876    dump_store_bat(env, 'I', 1, nr, value);
1877    env->IBAT[1][nr] = value;
1878}
1879
1880void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1881{
1882    target_ulong mask;
1883#if defined(FLUSH_ALL_TLBS)
1884    PowerPCCPU *cpu = ppc_env_get_cpu(env);
1885#endif
1886
1887    dump_store_bat(env, 'D', 0, nr, value);
1888    if (env->DBAT[0][nr] != value) {
1889        /* When storing valid upper BAT, mask BEPI and BRPN
1890         * and invalidate all TLBs covered by this BAT
1891         */
1892        mask = (value << 15) & 0x0FFE0000UL;
1893#if !defined(FLUSH_ALL_TLBS)
1894        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1895#endif
1896        mask = (value << 15) & 0x0FFE0000UL;
1897        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1898            (value & ~0x0001FFFFUL & ~mask);
1899        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1900            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1901#if !defined(FLUSH_ALL_TLBS)
1902        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1903#else
1904        tlb_flush(CPU(cpu));
1905#endif
1906    }
1907}
1908
1909void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1910{
1911    dump_store_bat(env, 'D', 1, nr, value);
1912    env->DBAT[1][nr] = value;
1913}
1914
1915void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
1916{
1917    target_ulong mask;
1918#if defined(FLUSH_ALL_TLBS)
1919    PowerPCCPU *cpu = ppc_env_get_cpu(env);
1920    int do_inval;
1921#endif
1922
1923    dump_store_bat(env, 'I', 0, nr, value);
1924    if (env->IBAT[0][nr] != value) {
1925#if defined(FLUSH_ALL_TLBS)
1926        do_inval = 0;
1927#endif
1928        mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1929        if (env->IBAT[1][nr] & 0x40) {
1930            /* Invalidate BAT only if it is valid */
1931#if !defined(FLUSH_ALL_TLBS)
1932            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1933#else
1934            do_inval = 1;
1935#endif
1936        }
1937        /* When storing valid upper BAT, mask BEPI and BRPN
1938         * and invalidate all TLBs covered by this BAT
1939         */
1940        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1941            (value & ~0x0001FFFFUL & ~mask);
1942        env->DBAT[0][nr] = env->IBAT[0][nr];
1943        if (env->IBAT[1][nr] & 0x40) {
1944#if !defined(FLUSH_ALL_TLBS)
1945            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1946#else
1947            do_inval = 1;
1948#endif
1949        }
1950#if defined(FLUSH_ALL_TLBS)
1951        if (do_inval) {
1952            tlb_flush(CPU(cpu));
1953        }
1954#endif
1955    }
1956}
1957
1958void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
1959{
1960#if !defined(FLUSH_ALL_TLBS)
1961    target_ulong mask;
1962#else
1963    PowerPCCPU *cpu = ppc_env_get_cpu(env);
1964    int do_inval;
1965#endif
1966
1967    dump_store_bat(env, 'I', 1, nr, value);
1968    if (env->IBAT[1][nr] != value) {
1969#if defined(FLUSH_ALL_TLBS)
1970        do_inval = 0;
1971#endif
1972        if (env->IBAT[1][nr] & 0x40) {
1973#if !defined(FLUSH_ALL_TLBS)
1974            mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1975            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1976#else
1977            do_inval = 1;
1978#endif
1979        }
1980        if (value & 0x40) {
1981#if !defined(FLUSH_ALL_TLBS)
1982            mask = (value << 17) & 0x0FFE0000UL;
1983            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1984#else
1985            do_inval = 1;
1986#endif
1987        }
1988        env->IBAT[1][nr] = value;
1989        env->DBAT[1][nr] = value;
1990#if defined(FLUSH_ALL_TLBS)
1991        if (do_inval) {
1992            tlb_flush(CPU(cpu));
1993        }
1994#endif
1995    }
1996}
1997
1998/*****************************************************************************/
1999/* TLB management */
2000void ppc_tlb_invalidate_all(CPUPPCState *env)
2001{
2002    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2003
2004#if defined(TARGET_PPC64)
2005    if (env->mmu_model & POWERPC_MMU_64) {
2006        env->tlb_need_flush = 0;
2007        tlb_flush(CPU(cpu));
2008    } else
2009#endif /* defined(TARGET_PPC64) */
2010    switch (env->mmu_model) {
2011    case POWERPC_MMU_SOFT_6xx:
2012    case POWERPC_MMU_SOFT_74xx:
2013        ppc6xx_tlb_invalidate_all(env);
2014        break;
2015    case POWERPC_MMU_SOFT_4xx:
2016    case POWERPC_MMU_SOFT_4xx_Z:
2017        ppc4xx_tlb_invalidate_all(env);
2018        break;
2019    case POWERPC_MMU_REAL:
2020        cpu_abort(CPU(cpu), "No TLB for PowerPC 4xx in real mode\n");
2021        break;
2022    case POWERPC_MMU_MPC8xx:
2023        /* XXX: TODO */
2024        cpu_abort(CPU(cpu), "MPC8xx MMU model is not implemented\n");
2025        break;
2026    case POWERPC_MMU_BOOKE:
2027        tlb_flush(CPU(cpu));
2028        break;
2029    case POWERPC_MMU_BOOKE206:
2030        booke206_flush_tlb(env, -1, 0);
2031        break;
2032    case POWERPC_MMU_32B:
2033    case POWERPC_MMU_601:
2034        env->tlb_need_flush = 0;
2035        tlb_flush(CPU(cpu));
2036        break;
2037    default:
2038        /* XXX: TODO */
2039        cpu_abort(CPU(cpu), "Unknown MMU model %x\n", env->mmu_model);
2040        break;
2041    }
2042}
2043
2044void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
2045{
2046#if !defined(FLUSH_ALL_TLBS)
2047    addr &= TARGET_PAGE_MASK;
2048#if defined(TARGET_PPC64)
2049    if (env->mmu_model & POWERPC_MMU_64) {
2050        /* tlbie invalidate TLBs for all segments */
2051        /* XXX: given the fact that there are too many segments to invalidate,
2052         *      and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
2053         *      we just invalidate all TLBs
2054         */
2055        env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2056    } else
2057#endif /* defined(TARGET_PPC64) */
2058    switch (env->mmu_model) {
2059    case POWERPC_MMU_SOFT_6xx:
2060    case POWERPC_MMU_SOFT_74xx:
2061        ppc6xx_tlb_invalidate_virt(env, addr, 0);
2062        if (env->id_tlbs == 1) {
2063            ppc6xx_tlb_invalidate_virt(env, addr, 1);
2064        }
2065        break;
2066    case POWERPC_MMU_32B:
2067    case POWERPC_MMU_601:
2068        /* Actual CPUs invalidate entire congruence classes based on the
2069         * geometry of their TLBs and some OSes take that into account,
2070         * we just mark the TLB to be flushed later (context synchronizing
2071         * event or sync instruction on 32-bit).
2072         */
2073        env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2074        break;
2075    default:
2076        /* Should never reach here with other MMU models */
2077        assert(0);
2078    }
2079#else
2080    ppc_tlb_invalidate_all(env);
2081#endif
2082}
2083
2084/*****************************************************************************/
2085/* Special registers manipulation */
2086void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
2087{
2088    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2089    qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
2090    assert(!cpu->vhyp);
2091#if defined(TARGET_PPC64)
2092    if (env->mmu_model & POWERPC_MMU_64) {
2093        target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
2094        target_ulong htabsize = value & SDR_64_HTABSIZE;
2095
2096        if (value & ~sdr_mask) {
2097            error_report("Invalid bits 0x"TARGET_FMT_lx" set in SDR1",
2098                         value & ~sdr_mask);
2099            value &= sdr_mask;
2100        }
2101        if (htabsize > 28) {
2102            error_report("Invalid HTABSIZE 0x" TARGET_FMT_lx" stored in SDR1",
2103                         htabsize);
2104            return;
2105        }
2106    }
2107#endif /* defined(TARGET_PPC64) */
2108    /* FIXME: Should check for valid HTABMASK values in 32-bit case */
2109    env->spr[SPR_SDR1] = value;
2110}
2111
2112#if defined(TARGET_PPC64)
2113void ppc_store_ptcr(CPUPPCState *env, target_ulong value)
2114{
2115    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2116    target_ulong ptcr_mask = PTCR_PATB | PTCR_PATS;
2117    target_ulong patbsize = value & PTCR_PATS;
2118
2119    qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
2120
2121    assert(!cpu->vhyp);
2122    assert(env->mmu_model & POWERPC_MMU_3_00);
2123
2124    if (value & ~ptcr_mask) {
2125        error_report("Invalid bits 0x"TARGET_FMT_lx" set in PTCR",
2126                     value & ~ptcr_mask);
2127        value &= ptcr_mask;
2128    }
2129
2130    if (patbsize > 24) {
2131        error_report("Invalid Partition Table size 0x" TARGET_FMT_lx
2132                     " stored in PTCR", patbsize);
2133        return;
2134    }
2135
2136    env->spr[SPR_PTCR] = value;
2137}
2138
2139#endif /* defined(TARGET_PPC64) */
2140
2141/* Segment registers load and store */
2142target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
2143{
2144#if defined(TARGET_PPC64)
2145    if (env->mmu_model & POWERPC_MMU_64) {
2146        /* XXX */
2147        return 0;
2148    }
2149#endif
2150    return env->sr[sr_num];
2151}
2152
2153void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
2154{
2155    qemu_log_mask(CPU_LOG_MMU,
2156            "%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2157            (int)srnum, value, env->sr[srnum]);
2158#if defined(TARGET_PPC64)
2159    if (env->mmu_model & POWERPC_MMU_64) {
2160        PowerPCCPU *cpu = ppc_env_get_cpu(env);
2161        uint64_t esid, vsid;
2162
2163        /* ESID = srnum */
2164        esid = ((uint64_t)(srnum & 0xf) << 28) | SLB_ESID_V;
2165
2166        /* VSID = VSID */
2167        vsid = (value & 0xfffffff) << 12;
2168        /* flags = flags */
2169        vsid |= ((value >> 27) & 0xf) << 8;
2170
2171        ppc_store_slb(cpu, srnum, esid, vsid);
2172    } else
2173#endif
2174    if (env->sr[srnum] != value) {
2175        env->sr[srnum] = value;
2176/* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2177   flusing the whole TLB. */
2178#if !defined(FLUSH_ALL_TLBS) && 0
2179        {
2180            target_ulong page, end;
2181            /* Invalidate 256 MB of virtual memory */
2182            page = (16 << 20) * srnum;
2183            end = page + (16 << 20);
2184            for (; page != end; page += TARGET_PAGE_SIZE) {
2185                tlb_flush_page(CPU(cpu), page);
2186            }
2187        }
2188#else
2189        env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2190#endif
2191    }
2192}
2193
2194/* TLB management */
2195void helper_tlbia(CPUPPCState *env)
2196{
2197    ppc_tlb_invalidate_all(env);
2198}
2199
2200void helper_tlbie(CPUPPCState *env, target_ulong addr)
2201{
2202    ppc_tlb_invalidate_one(env, addr);
2203}
2204
2205void helper_tlbiva(CPUPPCState *env, target_ulong addr)
2206{
2207    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2208
2209    /* tlbiva instruction only exists on BookE */
2210    assert(env->mmu_model == POWERPC_MMU_BOOKE);
2211    /* XXX: TODO */
2212    cpu_abort(CPU(cpu), "BookE MMU model is not implemented\n");
2213}
2214
2215/* Software driven TLBs management */
2216/* PowerPC 602/603 software TLB load instructions helpers */
2217static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2218{
2219    target_ulong RPN, CMP, EPN;
2220    int way;
2221
2222    RPN = env->spr[SPR_RPA];
2223    if (is_code) {
2224        CMP = env->spr[SPR_ICMP];
2225        EPN = env->spr[SPR_IMISS];
2226    } else {
2227        CMP = env->spr[SPR_DCMP];
2228        EPN = env->spr[SPR_DMISS];
2229    }
2230    way = (env->spr[SPR_SRR1] >> 17) & 1;
2231    (void)EPN; /* avoid a compiler warning */
2232    LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2233              " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2234              RPN, way);
2235    /* Store this TLB */
2236    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2237                     way, is_code, CMP, RPN);
2238}
2239
2240void helper_6xx_tlbd(CPUPPCState *env, target_ulong EPN)
2241{
2242    do_6xx_tlb(env, EPN, 0);
2243}
2244
2245void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
2246{
2247    do_6xx_tlb(env, EPN, 1);
2248}
2249
2250/* PowerPC 74xx software TLB load instructions helpers */
2251static void do_74xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2252{
2253    target_ulong RPN, CMP, EPN;
2254    int way;
2255
2256    RPN = env->spr[SPR_PTELO];
2257    CMP = env->spr[SPR_PTEHI];
2258    EPN = env->spr[SPR_TLBMISS] & ~0x3;
2259    way = env->spr[SPR_TLBMISS] & 0x3;
2260    (void)EPN; /* avoid a compiler warning */
2261    LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2262              " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2263              RPN, way);
2264    /* Store this TLB */
2265    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2266                     way, is_code, CMP, RPN);
2267}
2268
2269void helper_74xx_tlbd(CPUPPCState *env, target_ulong EPN)
2270{
2271    do_74xx_tlb(env, EPN, 0);
2272}
2273
2274void helper_74xx_tlbi(CPUPPCState *env, target_ulong EPN)
2275{
2276    do_74xx_tlb(env, EPN, 1);
2277}
2278
2279/*****************************************************************************/
2280/* PowerPC 601 specific instructions (POWER bridge) */
2281
2282target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
2283{
2284    mmu_ctx_t ctx;
2285    int nb_BATs;
2286    target_ulong ret = 0;
2287
2288    /* We don't have to generate many instances of this instruction,
2289     * as rac is supervisor only.
2290     */
2291    /* XXX: FIX THIS: Pretend we have no BAT */
2292    nb_BATs = env->nb_BATs;
2293    env->nb_BATs = 0;
2294    if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) {
2295        ret = ctx.raddr;
2296    }
2297    env->nb_BATs = nb_BATs;
2298    return ret;
2299}
2300
2301static inline target_ulong booke_tlb_to_page_size(int size)
2302{
2303    return 1024 << (2 * size);
2304}
2305
2306static inline int booke_page_size_to_tlb(target_ulong page_size)
2307{
2308    int size;
2309
2310    switch (page_size) {
2311    case 0x00000400UL:
2312        size = 0x0;
2313        break;
2314    case 0x00001000UL:
2315        size = 0x1;
2316        break;
2317    case 0x00004000UL:
2318        size = 0x2;
2319        break;
2320    case 0x00010000UL:
2321        size = 0x3;
2322        break;
2323    case 0x00040000UL:
2324        size = 0x4;
2325        break;
2326    case 0x00100000UL:
2327        size = 0x5;
2328        break;
2329    case 0x00400000UL:
2330        size = 0x6;
2331        break;
2332    case 0x01000000UL:
2333        size = 0x7;
2334        break;
2335    case 0x04000000UL:
2336        size = 0x8;
2337        break;
2338    case 0x10000000UL:
2339        size = 0x9;
2340        break;
2341    case 0x40000000UL:
2342        size = 0xA;
2343        break;
2344#if defined(TARGET_PPC64)
2345    case 0x000100000000ULL:
2346        size = 0xB;
2347        break;
2348    case 0x000400000000ULL:
2349        size = 0xC;
2350        break;
2351    case 0x001000000000ULL:
2352        size = 0xD;
2353        break;
2354    case 0x004000000000ULL:
2355        size = 0xE;
2356        break;
2357    case 0x010000000000ULL:
2358        size = 0xF;
2359        break;
2360#endif
2361    default:
2362        size = -1;
2363        break;
2364    }
2365
2366    return size;
2367}
2368
2369/* Helpers for 4xx TLB management */
2370#define PPC4XX_TLB_ENTRY_MASK       0x0000003f  /* Mask for 64 TLB entries */
2371
2372#define PPC4XX_TLBHI_V              0x00000040
2373#define PPC4XX_TLBHI_E              0x00000020
2374#define PPC4XX_TLBHI_SIZE_MIN       0
2375#define PPC4XX_TLBHI_SIZE_MAX       7
2376#define PPC4XX_TLBHI_SIZE_DEFAULT   1
2377#define PPC4XX_TLBHI_SIZE_SHIFT     7
2378#define PPC4XX_TLBHI_SIZE_MASK      0x00000007
2379
2380#define PPC4XX_TLBLO_EX             0x00000200
2381#define PPC4XX_TLBLO_WR             0x00000100
2382#define PPC4XX_TLBLO_ATTR_MASK      0x000000FF
2383#define PPC4XX_TLBLO_RPN_MASK       0xFFFFFC00
2384
2385target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry)
2386{
2387    ppcemb_tlb_t *tlb;
2388    target_ulong ret;
2389    int size;
2390
2391    entry &= PPC4XX_TLB_ENTRY_MASK;
2392    tlb = &env->tlb.tlbe[entry];
2393    ret = tlb->EPN;
2394    if (tlb->prot & PAGE_VALID) {
2395        ret |= PPC4XX_TLBHI_V;
2396    }
2397    size = booke_page_size_to_tlb(tlb->size);
2398    if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) {
2399        size = PPC4XX_TLBHI_SIZE_DEFAULT;
2400    }
2401    ret |= size << PPC4XX_TLBHI_SIZE_SHIFT;
2402    env->spr[SPR_40x_PID] = tlb->PID;
2403    return ret;
2404}
2405
2406target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, target_ulong entry)
2407{
2408    ppcemb_tlb_t *tlb;
2409    target_ulong ret;
2410
2411    entry &= PPC4XX_TLB_ENTRY_MASK;
2412    tlb = &env->tlb.tlbe[entry];
2413    ret = tlb->RPN;
2414    if (tlb->prot & PAGE_EXEC) {
2415        ret |= PPC4XX_TLBLO_EX;
2416    }
2417    if (tlb->prot & PAGE_WRITE) {
2418        ret |= PPC4XX_TLBLO_WR;
2419    }
2420    return ret;
2421}
2422
2423void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
2424                         target_ulong val)
2425{
2426    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2427    CPUState *cs = CPU(cpu);
2428    ppcemb_tlb_t *tlb;
2429    target_ulong page, end;
2430
2431    LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
2432              val);
2433    entry &= PPC4XX_TLB_ENTRY_MASK;
2434    tlb = &env->tlb.tlbe[entry];
2435    /* Invalidate previous TLB (if it's valid) */
2436    if (tlb->prot & PAGE_VALID) {
2437        end = tlb->EPN + tlb->size;
2438        LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end "
2439                  TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2440        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2441            tlb_flush_page(cs, page);
2442        }
2443    }
2444    tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
2445                                       & PPC4XX_TLBHI_SIZE_MASK);
2446    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2447     * If this ever occurs, we should implement TARGET_PAGE_BITS_VARY
2448     */
2449    if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
2450        cpu_abort(cs, "TLB size " TARGET_FMT_lu " < %u "
2451                  "are not supported (%d)\n"
2452                  "Please implement TARGET_PAGE_BITS_VARY\n",
2453                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
2454    }
2455    tlb->EPN = val & ~(tlb->size - 1);
2456    if (val & PPC4XX_TLBHI_V) {
2457        tlb->prot |= PAGE_VALID;
2458        if (val & PPC4XX_TLBHI_E) {
2459            /* XXX: TO BE FIXED */
2460            cpu_abort(cs,
2461                      "Little-endian TLB entries are not supported by now\n");
2462        }
2463    } else {
2464        tlb->prot &= ~PAGE_VALID;
2465    }
2466    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2467    LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2468              " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2469              (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2470              tlb->prot & PAGE_READ ? 'r' : '-',
2471              tlb->prot & PAGE_WRITE ? 'w' : '-',
2472              tlb->prot & PAGE_EXEC ? 'x' : '-',
2473              tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2474    /* Invalidate new TLB (if valid) */
2475    if (tlb->prot & PAGE_VALID) {
2476        end = tlb->EPN + tlb->size;
2477        LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end "
2478                  TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2479        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2480            tlb_flush_page(cs, page);
2481        }
2482    }
2483}
2484
2485void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry,
2486                         target_ulong val)
2487{
2488    ppcemb_tlb_t *tlb;
2489
2490    LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
2491              val);
2492    entry &= PPC4XX_TLB_ENTRY_MASK;
2493    tlb = &env->tlb.tlbe[entry];
2494    tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
2495    tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
2496    tlb->prot = PAGE_READ;
2497    if (val & PPC4XX_TLBLO_EX) {
2498        tlb->prot |= PAGE_EXEC;
2499    }
2500    if (val & PPC4XX_TLBLO_WR) {
2501        tlb->prot |= PAGE_WRITE;
2502    }
2503    LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2504              " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2505              (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2506              tlb->prot & PAGE_READ ? 'r' : '-',
2507              tlb->prot & PAGE_WRITE ? 'w' : '-',
2508              tlb->prot & PAGE_EXEC ? 'x' : '-',
2509              tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2510}
2511
2512target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address)
2513{
2514    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
2515}
2516
2517/* PowerPC 440 TLB management */
2518void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry,
2519                      target_ulong value)
2520{
2521    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2522    ppcemb_tlb_t *tlb;
2523    target_ulong EPN, RPN, size;
2524    int do_flush_tlbs;
2525
2526    LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n",
2527              __func__, word, (int)entry, value);
2528    do_flush_tlbs = 0;
2529    entry &= 0x3F;
2530    tlb = &env->tlb.tlbe[entry];
2531    switch (word) {
2532    default:
2533        /* Just here to please gcc */
2534    case 0:
2535        EPN = value & 0xFFFFFC00;
2536        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) {
2537            do_flush_tlbs = 1;
2538        }
2539        tlb->EPN = EPN;
2540        size = booke_tlb_to_page_size((value >> 4) & 0xF);
2541        if ((tlb->prot & PAGE_VALID) && tlb->size < size) {
2542            do_flush_tlbs = 1;
2543        }
2544        tlb->size = size;
2545        tlb->attr &= ~0x1;
2546        tlb->attr |= (value >> 8) & 1;
2547        if (value & 0x200) {
2548            tlb->prot |= PAGE_VALID;
2549        } else {
2550            if (tlb->prot & PAGE_VALID) {
2551                tlb->prot &= ~PAGE_VALID;
2552                do_flush_tlbs = 1;
2553            }
2554        }
2555        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2556        if (do_flush_tlbs) {
2557            tlb_flush(CPU(cpu));
2558        }
2559        break;
2560    case 1:
2561        RPN = value & 0xFFFFFC0F;
2562        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) {
2563            tlb_flush(CPU(cpu));
2564        }
2565        tlb->RPN = RPN;
2566        break;
2567    case 2:
2568        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
2569        tlb->prot = tlb->prot & PAGE_VALID;
2570        if (value & 0x1) {
2571            tlb->prot |= PAGE_READ << 4;
2572        }
2573        if (value & 0x2) {
2574            tlb->prot |= PAGE_WRITE << 4;
2575        }
2576        if (value & 0x4) {
2577            tlb->prot |= PAGE_EXEC << 4;
2578        }
2579        if (value & 0x8) {
2580            tlb->prot |= PAGE_READ;
2581        }
2582        if (value & 0x10) {
2583            tlb->prot |= PAGE_WRITE;
2584        }
2585        if (value & 0x20) {
2586            tlb->prot |= PAGE_EXEC;
2587        }
2588        break;
2589    }
2590}
2591
2592target_ulong helper_440_tlbre(CPUPPCState *env, uint32_t word,
2593                              target_ulong entry)
2594{
2595    ppcemb_tlb_t *tlb;
2596    target_ulong ret;
2597    int size;
2598
2599    entry &= 0x3F;
2600    tlb = &env->tlb.tlbe[entry];
2601    switch (word) {
2602    default:
2603        /* Just here to please gcc */
2604    case 0:
2605        ret = tlb->EPN;
2606        size = booke_page_size_to_tlb(tlb->size);
2607        if (size < 0 || size > 0xF) {
2608            size = 1;
2609        }
2610        ret |= size << 4;
2611        if (tlb->attr & 0x1) {
2612            ret |= 0x100;
2613        }
2614        if (tlb->prot & PAGE_VALID) {
2615            ret |= 0x200;
2616        }
2617        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2618        env->spr[SPR_440_MMUCR] |= tlb->PID;
2619        break;
2620    case 1:
2621        ret = tlb->RPN;
2622        break;
2623    case 2:
2624        ret = tlb->attr & ~0x1;
2625        if (tlb->prot & (PAGE_READ << 4)) {
2626            ret |= 0x1;
2627        }
2628        if (tlb->prot & (PAGE_WRITE << 4)) {
2629            ret |= 0x2;
2630        }
2631        if (tlb->prot & (PAGE_EXEC << 4)) {
2632            ret |= 0x4;
2633        }
2634        if (tlb->prot & PAGE_READ) {
2635            ret |= 0x8;
2636        }
2637        if (tlb->prot & PAGE_WRITE) {
2638            ret |= 0x10;
2639        }
2640        if (tlb->prot & PAGE_EXEC) {
2641            ret |= 0x20;
2642        }
2643        break;
2644    }
2645    return ret;
2646}
2647
2648target_ulong helper_440_tlbsx(CPUPPCState *env, target_ulong address)
2649{
2650    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
2651}
2652
2653/* PowerPC BookE 2.06 TLB management */
2654
2655static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env)
2656{
2657    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2658    uint32_t tlbncfg = 0;
2659    int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
2660    int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
2661    int tlb;
2662
2663    tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2664    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
2665
2666    if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
2667        cpu_abort(CPU(cpu), "we don't support HES yet\n");
2668    }
2669
2670    return booke206_get_tlbm(env, tlb, ea, esel);
2671}
2672
2673void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid)
2674{
2675    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2676
2677    env->spr[pidn] = pid;
2678    /* changing PIDs mean we're in a different address space now */
2679    tlb_flush(CPU(cpu));
2680}
2681
2682void helper_booke_set_eplc(CPUPPCState *env, target_ulong val)
2683{
2684    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2685    env->spr[SPR_BOOKE_EPLC] = val & EPID_MASK;
2686    tlb_flush_by_mmuidx(CPU(cpu), 1 << PPC_TLB_EPID_LOAD);
2687}
2688void helper_booke_set_epsc(CPUPPCState *env, target_ulong val)
2689{
2690    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2691    env->spr[SPR_BOOKE_EPSC] = val & EPID_MASK;
2692    tlb_flush_by_mmuidx(CPU(cpu), 1 << PPC_TLB_EPID_STORE);
2693}
2694
2695static inline void flush_page(CPUPPCState *env, ppcmas_tlb_t *tlb)
2696{
2697    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2698
2699    if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
2700        tlb_flush_page(CPU(cpu), tlb->mas2 & MAS2_EPN_MASK);
2701    } else {
2702        tlb_flush(CPU(cpu));
2703    }
2704}
2705
2706void helper_booke206_tlbwe(CPUPPCState *env)
2707{
2708    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2709    uint32_t tlbncfg, tlbn;
2710    ppcmas_tlb_t *tlb;
2711    uint32_t size_tlb, size_ps;
2712    target_ulong mask;
2713
2714
2715    switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
2716    case MAS0_WQ_ALWAYS:
2717        /* good to go, write that entry */
2718        break;
2719    case MAS0_WQ_COND:
2720        /* XXX check if reserved */
2721        if (0) {
2722            return;
2723        }
2724        break;
2725    case MAS0_WQ_CLR_RSRV:
2726        /* XXX clear entry */
2727        return;
2728    default:
2729        /* no idea what to do */
2730        return;
2731    }
2732
2733    if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
2734        !msr_gs) {
2735        /* XXX we don't support direct LRAT setting yet */
2736        fprintf(stderr, "cpu: don't support LRAT setting yet\n");
2737        return;
2738    }
2739
2740    tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2741    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
2742
2743    tlb = booke206_cur_tlb(env);
2744
2745    if (!tlb) {
2746        raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2747                               POWERPC_EXCP_INVAL |
2748                               POWERPC_EXCP_INVAL_INVAL, GETPC());
2749    }
2750
2751    /* check that we support the targeted size */
2752    size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
2753    size_ps = booke206_tlbnps(env, tlbn);
2754    if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
2755        !(size_ps & (1 << size_tlb))) {
2756        raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2757                               POWERPC_EXCP_INVAL |
2758                               POWERPC_EXCP_INVAL_INVAL, GETPC());
2759    }
2760
2761    if (msr_gs) {
2762        cpu_abort(CPU(cpu), "missing HV implementation\n");
2763    }
2764
2765    if (tlb->mas1 & MAS1_VALID) {
2766        /* Invalidate the page in QEMU TLB if it was a valid entry.
2767         *
2768         * In "PowerPC e500 Core Family Reference Manual, Rev. 1",
2769         * Section "12.4.2 TLB Write Entry (tlbwe) Instruction":
2770         * (https://www.nxp.com/docs/en/reference-manual/E500CORERM.pdf)
2771         *
2772         * "Note that when an L2 TLB entry is written, it may be displacing an
2773         * already valid entry in the same L2 TLB location (a victim). If a
2774         * valid L1 TLB entry corresponds to the L2 MMU victim entry, that L1
2775         * TLB entry is automatically invalidated." */
2776        flush_page(env, tlb);
2777    }
2778
2779    tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
2780        env->spr[SPR_BOOKE_MAS3];
2781    tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
2782
2783    if ((env->spr[SPR_MMUCFG] & MMUCFG_MAVN) == MMUCFG_MAVN_V2) {
2784        /* For TLB which has a fixed size TSIZE is ignored with MAV2 */
2785        booke206_fixed_size_tlbn(env, tlbn, tlb);
2786    } else {
2787        if (!(tlbncfg & TLBnCFG_AVAIL)) {
2788            /* force !AVAIL TLB entries to correct page size */
2789            tlb->mas1 &= ~MAS1_TSIZE_MASK;
2790            /* XXX can be configured in MMUCSR0 */
2791            tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
2792        }
2793    }
2794
2795    /* Make a mask from TLB size to discard invalid bits in EPN field */
2796    mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2797    /* Add a mask for page attributes */
2798    mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E;
2799
2800    if (!msr_cm) {
2801        /* Executing a tlbwe instruction in 32-bit mode will set
2802         * bits 0:31 of the TLB EPN field to zero.
2803         */
2804        mask &= 0xffffffff;
2805    }
2806
2807    tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask;
2808
2809    if (!(tlbncfg & TLBnCFG_IPROT)) {
2810        /* no IPROT supported by TLB */
2811        tlb->mas1 &= ~MAS1_IPROT;
2812    }
2813
2814    flush_page(env, tlb);
2815}
2816
2817static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb)
2818{
2819    int tlbn = booke206_tlbm_to_tlbn(env, tlb);
2820    int way = booke206_tlbm_to_way(env, tlb);
2821
2822    env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
2823    env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
2824    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2825
2826    env->spr[SPR_BOOKE_MAS1] = tlb->mas1;
2827    env->spr[SPR_BOOKE_MAS2] = tlb->mas2;
2828    env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3;
2829    env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32;
2830}
2831
2832void helper_booke206_tlbre(CPUPPCState *env)
2833{
2834    ppcmas_tlb_t *tlb = NULL;
2835
2836    tlb = booke206_cur_tlb(env);
2837    if (!tlb) {
2838        env->spr[SPR_BOOKE_MAS1] = 0;
2839    } else {
2840        booke206_tlb_to_mas(env, tlb);
2841    }
2842}
2843
2844void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address)
2845{
2846    ppcmas_tlb_t *tlb = NULL;
2847    int i, j;
2848    hwaddr raddr;
2849    uint32_t spid, sas;
2850
2851    spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
2852    sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
2853
2854    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2855        int ways = booke206_tlb_ways(env, i);
2856
2857        for (j = 0; j < ways; j++) {
2858            tlb = booke206_get_tlbm(env, i, address, j);
2859
2860            if (!tlb) {
2861                continue;
2862            }
2863
2864            if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
2865                continue;
2866            }
2867
2868            if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
2869                continue;
2870            }
2871
2872            booke206_tlb_to_mas(env, tlb);
2873            return;
2874        }
2875    }
2876
2877    /* no entry found, fill with defaults */
2878    env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
2879    env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
2880    env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
2881    env->spr[SPR_BOOKE_MAS3] = 0;
2882    env->spr[SPR_BOOKE_MAS7] = 0;
2883
2884    if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
2885        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
2886    }
2887
2888    env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
2889        << MAS1_TID_SHIFT;
2890
2891    /* next victim logic */
2892    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
2893    env->last_way++;
2894    env->last_way &= booke206_tlb_ways(env, 0) - 1;
2895    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2896}
2897
2898static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
2899                                              uint32_t ea)
2900{
2901    int i;
2902    int ways = booke206_tlb_ways(env, tlbn);
2903    target_ulong mask;
2904
2905    for (i = 0; i < ways; i++) {
2906        ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
2907        if (!tlb) {
2908            continue;
2909        }
2910        mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2911        if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
2912            !(tlb->mas1 & MAS1_IPROT)) {
2913            tlb->mas1 &= ~MAS1_VALID;
2914        }
2915    }
2916}
2917
2918void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
2919{
2920    CPUState *cs;
2921
2922    if (address & 0x4) {
2923        /* flush all entries */
2924        if (address & 0x8) {
2925            /* flush all of TLB1 */
2926            booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
2927        } else {
2928            /* flush all of TLB0 */
2929            booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
2930        }
2931        return;
2932    }
2933
2934    if (address & 0x8) {
2935        /* flush TLB1 entries */
2936        booke206_invalidate_ea_tlb(env, 1, address);
2937        CPU_FOREACH(cs) {
2938            tlb_flush(cs);
2939        }
2940    } else {
2941        /* flush TLB0 entries */
2942        booke206_invalidate_ea_tlb(env, 0, address);
2943        CPU_FOREACH(cs) {
2944            tlb_flush_page(cs, address & MAS2_EPN_MASK);
2945        }
2946    }
2947}
2948
2949void helper_booke206_tlbilx0(CPUPPCState *env, target_ulong address)
2950{
2951    /* XXX missing LPID handling */
2952    booke206_flush_tlb(env, -1, 1);
2953}
2954
2955void helper_booke206_tlbilx1(CPUPPCState *env, target_ulong address)
2956{
2957    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2958    int i, j;
2959    int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2960    ppcmas_tlb_t *tlb = env->tlb.tlbm;
2961    int tlb_size;
2962
2963    /* XXX missing LPID handling */
2964    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2965        tlb_size = booke206_tlb_size(env, i);
2966        for (j = 0; j < tlb_size; j++) {
2967            if (!(tlb[j].mas1 & MAS1_IPROT) &&
2968                ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
2969                tlb[j].mas1 &= ~MAS1_VALID;
2970            }
2971        }
2972        tlb += booke206_tlb_size(env, i);
2973    }
2974    tlb_flush(CPU(cpu));
2975}
2976
2977void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address)
2978{
2979    PowerPCCPU *cpu = ppc_env_get_cpu(env);
2980    int i, j;
2981    ppcmas_tlb_t *tlb;
2982    int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2983    int pid = tid >> MAS6_SPID_SHIFT;
2984    int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
2985    int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
2986    /* XXX check for unsupported isize and raise an invalid opcode then */
2987    int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
2988    /* XXX implement MAV2 handling */
2989    bool mav2 = false;
2990
2991    /* XXX missing LPID handling */
2992    /* flush by pid and ea */
2993    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2994        int ways = booke206_tlb_ways(env, i);
2995
2996        for (j = 0; j < ways; j++) {
2997            tlb = booke206_get_tlbm(env, i, address, j);
2998            if (!tlb) {
2999                continue;
3000            }
3001            if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
3002                (tlb->mas1 & MAS1_IPROT) ||
3003                ((tlb->mas1 & MAS1_IND) != ind) ||
3004                ((tlb->mas8 & MAS8_TGS) != sgs)) {
3005                continue;
3006            }
3007            if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
3008                /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
3009                continue;
3010            }
3011            /* XXX e500mc doesn't match SAS, but other cores might */
3012            tlb->mas1 &= ~MAS1_VALID;
3013        }
3014    }
3015    tlb_flush(CPU(cpu));
3016}
3017
3018void helper_booke206_tlbflush(CPUPPCState *env, target_ulong type)
3019{
3020    int flags = 0;
3021
3022    if (type & 2) {
3023        flags |= BOOKE206_FLUSH_TLB1;
3024    }
3025
3026    if (type & 4) {
3027        flags |= BOOKE206_FLUSH_TLB0;
3028    }
3029
3030    booke206_flush_tlb(env, flags, 1);
3031}
3032
3033
3034void helper_check_tlb_flush_local(CPUPPCState *env)
3035{
3036    check_tlb_flush(env, false);
3037}
3038
3039void helper_check_tlb_flush_global(CPUPPCState *env)
3040{
3041    check_tlb_flush(env, true);
3042}
3043
3044/*****************************************************************************/
3045
3046/* try to fill the TLB and return an exception if error. If retaddr is
3047   NULL, it means that the function was called in C code (i.e. not
3048   from generated code or from helper.c) */
3049/* XXX: fix it to restore all registers */
3050void tlb_fill(CPUState *cs, target_ulong addr, int size,
3051              MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
3052{
3053    PowerPCCPU *cpu = POWERPC_CPU(cs);
3054    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
3055    CPUPPCState *env = &cpu->env;
3056    int ret;
3057
3058    if (pcc->handle_mmu_fault) {
3059        ret = pcc->handle_mmu_fault(cpu, addr, access_type, mmu_idx);
3060    } else {
3061        ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx);
3062    }
3063    if (unlikely(ret != 0)) {
3064        raise_exception_err_ra(env, cs->exception_index, env->error_code,
3065                               retaddr);
3066    }
3067}
3068