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