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