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